diff --git a/DEPS b/DEPS index 2b0f609..0033c4c 100644 --- a/DEPS +++ b/DEPS
@@ -74,11 +74,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '29c14a760682e2c449fa043b5e8b69937cb58f3a', + 'skia_revision': 'ef0384835757df463f5157145650a60ba8b14a63', # 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': '7be4ef7e83ff9f49dbc23635d6d4d9a81be3c387', + 'v8_revision': '62729327a2ac79da305d047df20949e075c8cd9a', # 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. @@ -86,7 +86,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '9d4d7f06facbe5db0f178be7b4126d6072d4ee69', + 'angle_revision': '647dca7672f709d2cc3896c5ffb2fd9b904a15e4', # 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. @@ -98,7 +98,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '667fa571db51cbd53e012898f11ead7172e9263c', + 'pdfium_revision': '682118834b3cf2b5510ee676088fdd8f11869e84', # 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. @@ -130,7 +130,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': 'f2d71764a1ecfe50ddbaef85835e1a1fdb45345e', + 'catapult_revision': 'ad4583d06ecd8aca6d3f4661f075f15b47e9dbf7', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -323,7 +323,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '41d9d87e9653e46166db0e97a184c801a28d75e3', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '47d7464952b6d63f2d437364f1260ee28b9b5b0f', # DevTools node modules. Used on Linux buildbots only. 'src/third_party/devtools-node-modules': { @@ -662,7 +662,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0bf4fdf50244d69c1fdcdcfbdad6a81eff8a3e68', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@c4c0a915669c4c9c7483e8eb8f8fe2619937588c', 'condition': 'checkout_src_internal', }, } @@ -947,9 +947,9 @@ { 'name': 'content_shell_fonts', 'pattern': '.', + 'condition': 'checkout_linux', 'action': [ 'download_from_google_storage', '--no_resume', - '--platform=linux*', '--extract', '--no_auth', '--bucket', 'chromium-fonts',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 3f61dedd..b3f9a99f 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -24,6 +24,8 @@ r"^gpu[\\\/]config[\\\/].*_list_json\.cc$", r"^chrome[\\\/]browser[\\\/]resources[\\\/]pdf[\\\/]index.js", r"tools[\\\/]md_browser[\\\/].*\.css$", + # Test pages for Maps telemetry tests. + r"tools[\\\/]perf[\\\/]page_sets[\\\/]maps_perf_test.*", # Test pages for WebRTC telemetry tests. r"tools[\\\/]perf[\\\/]page_sets[\\\/]webrtc_cases.*", )
diff --git a/WATCHLISTS b/WATCHLISTS index 2e400e1..525e49c 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -1610,7 +1610,6 @@ 'yuzo+watch@chromium.org'], 'add_to_homescreen': ['dominickn+watch@chromium.org', 'hanxi+watch@chromium.org', - 'piotrs+watch@chromium.org', 'pkotwicz+watch@chromium.org'], 'android_crash_reporting': ['asvitkine+watch@chromium.org'], 'android_crazy_linker': ['johnmaguire+watch@google.com'], @@ -1670,7 +1669,6 @@ 'peter@chromium.org'], 'banners': ['dominickn+watch@chromium.org', 'hanxi+watch@chromium.org', - 'piotrs+watch@chromium.org', 'pkotwicz+watch@chromium.org'], 'base': ['vmpstr+watch@chromium.org'], 'base_allocator': ['dmikurube@chromium.org', @@ -2040,8 +2038,7 @@ 'jsbell+idb@chromium.org'], 'ink_drop': ['bruthig+ink_drop@chromium.org'], 'input': ['dtapuska+chromiumwatch@chromium.org'], - 'installable': ['dominickn+watch@chromium.org', - 'piotrs+watch@chromium.org'], + 'installable': ['dominickn+watch@chromium.org'], 'installer_linux': ['mmoss@chromium.org', 'raphael.kubo.da.costa@intel.com'], 'installer_win': ['grt+watch@chromium.org',
diff --git a/android_webview/common/OWNERS b/android_webview/common/OWNERS index ba65dfb..42444bc 100644 --- a/android_webview/common/OWNERS +++ b/android_webview/common/OWNERS
@@ -1,2 +1,2 @@ -per-file *_messages*.h=set noparent -per-file *_messages*.h=file://ipc/SECURITY_OWNERS +per-file *_messages*.h=set noparent +per-file *_messages*.h=file://ipc/SECURITY_OWNERS
diff --git a/apps/DEPS b/apps/DEPS index 8d82771..ed600be3 100644 --- a/apps/DEPS +++ b/apps/DEPS
@@ -13,8 +13,8 @@ specific_include_rules = { "(.*test\.cc|.*test_mac\.mm)": [ "+chrome/browser/extensions/extension_browsertest.h", - "+chrome/browser/extensions/extension_error_reporter.h", "+chrome/browser/extensions/extension_test_message_listener.h", + "+chrome/browser/extensions/load_error_reporter.h", "+chrome/browser/extensions/test_extension_environment.h", "+chrome/browser/profiles/profile_manager.h", "+chrome/browser/ui/simple_message_box_internal.h",
diff --git a/apps/load_and_launch_browsertest.cc b/apps/load_and_launch_browsertest.cc index 7ebe7ca..fd7f87e4 100644 --- a/apps/load_and_launch_browsertest.cc +++ b/apps/load_and_launch_browsertest.cc
@@ -12,7 +12,7 @@ #include "base/test/test_timeouts.h" #include "chrome/browser/apps/app_browsertest_util.h" #include "chrome/browser/extensions/extension_browsertest.h" -#include "chrome/browser/extensions/extension_error_reporter.h" +#include "chrome/browser/extensions/load_error_reporter.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/simple_message_box_internal.h" #include "chrome/common/chrome_switches.h" @@ -180,7 +180,7 @@ IN_PROC_BROWSER_TEST_F(LoadAndLaunchExtensionBrowserTest, LoadAndLaunchExtension) { const std::vector<base::string16>* errors = - ExtensionErrorReporter::GetInstance()->GetErrors(); + extensions::LoadErrorReporter::GetInstance()->GetErrors(); #if defined(GOOGLE_CHROME_BUILD) // The error is skipped on official builds.
diff --git a/ash/display/display_manager_unittest.cc b/ash/display/display_manager_unittest.cc index db56bbe..77d84c6 100644 --- a/ash/display/display_manager_unittest.cc +++ b/ash/display/display_manager_unittest.cc
@@ -1262,14 +1262,11 @@ Shell::GetPrimaryRootWindow()->bounds().size().ToString()); } -display::ManagedDisplayInfo CreateDisplayInfo(int64_t id, - const gfx::Rect& bounds) { - display::ManagedDisplayInfo info(id, ToDisplayName(id), false); - info.SetBounds(bounds); - return info; -} - TEST_F(DisplayManagerTest, TestNativeDisplaysChanged) { + // Disable restoring mirror mode to prevent interference from previous + // display configuration. + display_manager()->set_disable_restoring_mirror_mode_for_test(true); + const int64_t internal_display_id = display::test::DisplayManagerTestApi(display_manager()) .SetFirstDisplayAsInternalDisplay(); @@ -1277,11 +1274,12 @@ const int mirror_id = 11; const int64_t invalid_id = display::kInvalidDisplayId; const display::ManagedDisplayInfo internal_display_info = - CreateDisplayInfo(internal_display_id, gfx::Rect(0, 0, 500, 500)); + display::CreateDisplayInfo(internal_display_id, + gfx::Rect(0, 0, 500, 500)); const display::ManagedDisplayInfo external_display_info = - CreateDisplayInfo(external_id, gfx::Rect(1, 1, 100, 100)); + display::CreateDisplayInfo(external_id, gfx::Rect(1, 1, 100, 100)); const display::ManagedDisplayInfo mirroring_display_info = - CreateDisplayInfo(mirror_id, gfx::Rect(0, 0, 500, 500)); + display::CreateDisplayInfo(mirror_id, gfx::Rect(0, 0, 500, 500)); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); EXPECT_EQ(1U, display_manager()->num_connected_displays()); @@ -1369,7 +1367,8 @@ // and resume with different external display. display_info_list.push_back(internal_display_info); - display_info_list.push_back(CreateDisplayInfo(12, gfx::Rect(1, 1, 100, 100))); + display_info_list.push_back( + display::CreateDisplayInfo(12, gfx::Rect(1, 1, 100, 100))); display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); EXPECT_EQ(2U, display_manager()->num_connected_displays()); @@ -1430,6 +1429,8 @@ GetDisplayInfoForId(internal_display_id).bounds_in_native().ToString()); EXPECT_EQ(1U, display_manager()->num_connected_displays()); EXPECT_FALSE(display_manager()->IsInMirrorMode()); + + display_manager()->set_disable_restoring_mirror_mode_for_test(false); } // Make sure crash does not happen if add and remove happens at the same time. @@ -1449,7 +1450,7 @@ const int64_t third_id = secondary_id + 1; display::ManagedDisplayInfo third_info = - CreateDisplayInfo(third_id, gfx::Rect(0, 0, 600, 600)); + display::CreateDisplayInfo(third_id, gfx::Rect(0, 0, 600, 600)); std::vector<display::ManagedDisplayInfo> display_info_list; display_info_list.push_back(third_info); @@ -1472,7 +1473,7 @@ // Connect another display which will become primary. const display::ManagedDisplayInfo external_display_info = - CreateDisplayInfo(10, gfx::Rect(1, 1, 100, 100)); + display::CreateDisplayInfo(10, gfx::Rect(1, 1, 100, 100)); display_info_list.push_back(external_display_info); display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); @@ -1490,9 +1491,10 @@ display::test::DisplayManagerTestApi(display_manager()) .SetFirstDisplayAsInternalDisplay(); const display::ManagedDisplayInfo native_display_info = - CreateDisplayInfo(internal_display_id, gfx::Rect(0, 0, 500, 500)); + display::CreateDisplayInfo(internal_display_id, + gfx::Rect(0, 0, 500, 500)); const display::ManagedDisplayInfo secondary_display_info = - CreateDisplayInfo(10, gfx::Rect(1, 1, 100, 100)); + display::CreateDisplayInfo(10, gfx::Rect(1, 1, 100, 100)); std::vector<display::ManagedDisplayInfo> display_info_list; display_info_list.push_back(native_display_info); @@ -1520,7 +1522,7 @@ TEST_F(DisplayManagerTest, DontRememberBestResolution) { int display_id = 1000; display::ManagedDisplayInfo native_display_info = - CreateDisplayInfo(display_id, gfx::Rect(0, 0, 1000, 500)); + display::CreateDisplayInfo(display_id, gfx::Rect(0, 0, 1000, 500)); display::ManagedDisplayInfo::ManagedDisplayModeList display_modes; display_modes.push_back( display::ManagedDisplayMode(gfx::Size(1000, 500), 58.0f, false, true)); @@ -1591,7 +1593,7 @@ TEST_F(DisplayManagerTest, ResolutionFallback) { int display_id = 1000; display::ManagedDisplayInfo native_display_info = - CreateDisplayInfo(display_id, gfx::Rect(0, 0, 1000, 500)); + display::CreateDisplayInfo(display_id, gfx::Rect(0, 0, 1000, 500)); display::ManagedDisplayInfo::ManagedDisplayModeList display_modes; display_modes.push_back( display::ManagedDisplayMode(gfx::Size(1000, 500), 58.0f, false, true)); @@ -1610,7 +1612,7 @@ display::test::SetDisplayResolution(display_manager(), display_id, gfx::Size(800, 300)); display::ManagedDisplayInfo new_native_display_info = - CreateDisplayInfo(display_id, gfx::Rect(0, 0, 400, 500)); + display::CreateDisplayInfo(display_id, gfx::Rect(0, 0, 400, 500)); copy = display_modes; new_native_display_info.SetManagedDisplayModes(copy); std::vector<display::ManagedDisplayInfo> new_display_info_list; @@ -1629,7 +1631,7 @@ display::test::SetDisplayResolution(display_manager(), display_id, gfx::Size(800, 300)); display::ManagedDisplayInfo new_native_display_info = - CreateDisplayInfo(display_id, gfx::Rect(0, 0, 1000, 500)); + display::CreateDisplayInfo(display_id, gfx::Rect(0, 0, 1000, 500)); display::ManagedDisplayInfo::ManagedDisplayModeList copy = display_modes; new_native_display_info.SetManagedDisplayModes(copy); std::vector<display::ManagedDisplayInfo> new_display_info_list; @@ -1849,7 +1851,7 @@ // Setup the display modes with UI-scale. display::ManagedDisplayInfo native_display_info = - CreateDisplayInfo(display_id, gfx::Rect(0, 0, 1280, 800)); + display::CreateDisplayInfo(display_id, gfx::Rect(0, 0, 1280, 800)); const display::ManagedDisplayMode base_mode(gfx::Size(1280, 800), 60.0f, false, false); display::ManagedDisplayInfo::ManagedDisplayModeList mode_list = @@ -1955,7 +1957,7 @@ const int display_id = 1000; display::ManagedDisplayInfo native_display_info = - CreateDisplayInfo(display_id, gfx::Rect(0, 0, 1920, 1080)); + display::CreateDisplayInfo(display_id, gfx::Rect(0, 0, 1920, 1080)); native_display_info.set_device_scale_factor(1.25f); native_display_info.SetManagedDisplayModes(mode_list); @@ -2025,7 +2027,7 @@ // Setup the display modes with UI-scale. display::ManagedDisplayInfo native_display_info = - CreateDisplayInfo(display_id, gfx::Rect(0, 0, 1920, 1080)); + display::CreateDisplayInfo(display_id, gfx::Rect(0, 0, 1920, 1080)); native_display_info.set_device_scale_factor(1.25); const display::ManagedDisplayMode base_mode(gfx::Size(1920, 1080), 60.0f, @@ -2058,7 +2060,7 @@ // Setup the display modes with UI-scale. display::ManagedDisplayInfo native_display_info = - CreateDisplayInfo(display_id, gfx::Rect(0, 0, 1920, 1080)); + display::CreateDisplayInfo(display_id, gfx::Rect(0, 0, 1920, 1080)); native_display_info.set_device_scale_factor(1.25); const display::ManagedDisplayMode base_mode(gfx::Size(1920, 1080), 60.0f, @@ -2280,28 +2282,6 @@ display_manager()->SetMirrorMode(false); } -TEST_F(DisplayManagerTest, SingleDisplayToSoftwareMirroring) { - UpdateDisplay("600x400"); - - display_manager()->SetMultiDisplayMode(display::DisplayManager::MIRRORING); - UpdateDisplay("600x400,600x400"); - - EXPECT_TRUE(display_manager()->IsInMirrorMode()); - EXPECT_EQ(1U, display_manager()->GetNumDisplays()); - WindowTreeHostManager* window_tree_host_manager = - ash::Shell::Get()->window_tree_host_manager(); - EXPECT_EQ(1U, window_tree_host_manager->mirror_window_controller() - ->GetAllRootWindows() - .size()); - - UpdateDisplay("600x400"); - EXPECT_FALSE(display_manager()->IsInMirrorMode()); - EXPECT_EQ(1U, display_manager()->GetNumDisplays()); - EXPECT_TRUE(window_tree_host_manager->mirror_window_controller() - ->GetAllRootWindows() - .empty()); -} - // TODO(weidongg/774795) Remove test when multi mirroring is enabled by default. // Make sure this does not cause any crashes. See http://crbug.com/412910 TEST_F(DisplayManagerTest, SoftwareMirroringWithCompositingCursor) { @@ -2336,12 +2316,17 @@ Shell::Get()->SetCursorCompositingEnabled(false); } -TEST_F(DisplayManagerTest, MirroredLayout) { +TEST_F(DisplayManagerTest, HardwareMirrorDetection) { + // Disable restoring mirror mode to prevent interference from previous + // display configuration. + display_manager()->set_disable_restoring_mirror_mode_for_test(true); + UpdateDisplay("500x500,400x400"); EXPECT_FALSE(display_manager()->GetCurrentDisplayLayout().mirrored); EXPECT_EQ(2, display::Screen::GetScreen()->GetNumDisplays()); EXPECT_EQ(2U, display_manager()->num_connected_displays()); + // Hardware mirroring. UpdateDisplay("1+0-500x500,1+0-500x500"); EXPECT_TRUE(display_manager()->GetCurrentDisplayLayout().mirrored); EXPECT_EQ(1, display::Screen::GetScreen()->GetNumDisplays()); @@ -2351,6 +2336,8 @@ EXPECT_FALSE(display_manager()->GetCurrentDisplayLayout().mirrored); EXPECT_EQ(2, display::Screen::GetScreen()->GetNumDisplays()); EXPECT_EQ(2U, display_manager()->num_connected_displays()); + + display_manager()->set_disable_restoring_mirror_mode_for_test(false); } TEST_F(DisplayManagerTest, InvertLayout) { @@ -2434,7 +2421,7 @@ // Assume the default display is an external display, and // emulates undocking by switching to another display. display::ManagedDisplayInfo another_display_info = - CreateDisplayInfo(1, gfx::Rect(0, 0, 1280, 800)); + display::CreateDisplayInfo(1, gfx::Rect(0, 0, 1280, 800)); std::vector<display::ManagedDisplayInfo> info_list; info_list.push_back(another_display_info); reset(); @@ -2515,9 +2502,10 @@ // The default should fit to the internal display. std::vector<display::ManagedDisplayInfo> display_info_list; - display_info_list.push_back(CreateDisplayInfo(10, gfx::Rect(0, 0, 500, 300))); display_info_list.push_back( - CreateDisplayInfo(11, gfx::Rect(500, 0, 400, 500))); + display::CreateDisplayInfo(10, gfx::Rect(0, 0, 500, 300))); + display_info_list.push_back( + display::CreateDisplayInfo(11, gfx::Rect(500, 0, 400, 500))); { display::test::ScopedSetInternalDisplayId set_internal(display_manager(), 11); @@ -2555,27 +2543,30 @@ display_info_list.push_back(d1); display_info_list.push_back(d2); display_manager()->OnNativeDisplaysChanged(display_info_list); - ASSERT_TRUE(display_manager()->IsInMirrorMode()); + ASSERT_TRUE(display_manager()->IsInHardwareMirrorMode()); display_manager()->SetUnifiedDesktopEnabled(true); - EXPECT_TRUE(display_manager()->IsInMirrorMode()); + EXPECT_TRUE(display_manager()->IsInHardwareMirrorMode()); - // The display manager automaticaclly switches to software mirroring - // if the displays are configured to use mirroring when running on desktop. - // This is a workdaround to force the display manager to forget - // the mirroing layout. + // The display manager automatically switches to software mirroring if + // hardware mirroring is no longer available, because previous mirror mode + // enforces current display mode to be mirror mode. display::DisplayIdList list = display::test::CreateDisplayIdList2(1, 2); display::DisplayLayoutBuilder builder( display_manager()->layout_store()->GetRegisteredDisplayLayout(list)); builder.SetMirrored(false); display_manager()->layout_store()->RegisterLayoutForDisplayIdList( list, builder.Build()); - - // Exit from hardware mirroring. d2.SetBounds(gfx::Rect(0, 500, 500, 500)); display_info_list.clear(); display_info_list.push_back(d1); display_info_list.push_back(d2); display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_TRUE(display_manager()->IsInSoftwareMirrorMode()); + EXPECT_FALSE(display_manager()->IsInUnifiedMode()); + + // Exit software mirroring and enter unified desktop mode after mirror mode is + // turned off. + display_manager()->SetMirrorMode(false); EXPECT_FALSE(display_manager()->IsInMirrorMode()); EXPECT_TRUE(display_manager()->IsInUnifiedMode()); } @@ -2888,9 +2879,9 @@ display_manager()->SetUnifiedDesktopMatrix(matrix); std::vector<display::ManagedDisplayInfo> display_info_list; display_info_list.emplace_back( - CreateDisplayInfo(list[0], gfx::Rect(0, 0, 400, 500))); + display::CreateDisplayInfo(list[0], gfx::Rect(0, 0, 400, 500))); display_info_list.emplace_back( - CreateDisplayInfo(list[1], gfx::Rect(400, 0, 300, 200))); + display::CreateDisplayInfo(list[1], gfx::Rect(400, 0, 300, 200))); display::test::ScopedSetInternalDisplayId set_internal(display_manager(), list[1]); display_manager()->OnNativeDisplaysChanged(display_info_list); @@ -3078,9 +3069,9 @@ const int64_t external_id = 2; const display::ManagedDisplayInfo internal_display_info = - CreateDisplayInfo(internal_id, gfx::Rect(0, 0, 500, 500)); + display::CreateDisplayInfo(internal_id, gfx::Rect(0, 0, 500, 500)); const display::ManagedDisplayInfo external_display_info = - CreateDisplayInfo(external_id, gfx::Rect(1, 1, 100, 100)); + display::CreateDisplayInfo(external_id, gfx::Rect(1, 1, 100, 100)); std::vector<display::ManagedDisplayInfo> display_info_list; // software mirroring. @@ -3340,15 +3331,15 @@ // Secondary is now primary and should not have accelerometer support. std::vector<display::ManagedDisplayInfo> display_info_list; display_info_list.push_back( - CreateDisplayInfo(display_manager()->GetSecondaryDisplay().id(), - gfx::Rect(1, 1, 100, 100))); + display::CreateDisplayInfo(display_manager()->GetSecondaryDisplay().id(), + gfx::Rect(1, 1, 100, 100))); display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(display::Display::ACCELEROMETER_SUPPORT_UNAVAILABLE, screen->GetPrimaryDisplay().accelerometer_support()); // Re-enable internal display. display_info_list.clear(); - display_info_list.push_back(CreateDisplayInfo( + display_info_list.push_back(display::CreateDisplayInfo( display::Display::InternalDisplayId(), gfx::Rect(1, 1, 100, 100))); display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(display::Display::ACCELEROMETER_SUPPORT_AVAILABLE, @@ -3468,6 +3459,10 @@ // It's difficult to test with full stack due to crbug.com/771178. // Improve the coverage once it is fixed. TEST_F(DisplayManagerTest, ForcedMirrorMode) { + // Disable restoring mirror mode to prevent interference from previous + // display configuration. + display_manager()->set_disable_restoring_mirror_mode_for_test(true); + constexpr int64_t id1 = 1; constexpr int64_t id2 = 2; display::Screen* screen = display::Screen::GetScreen(); @@ -3512,6 +3507,8 @@ EXPECT_EQ(display::MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED, observer.GetStateForDisplayIds(outputs)); + + display_manager()->set_disable_restoring_mirror_mode_for_test(false); } namespace { @@ -3830,15 +3827,15 @@ const int64_t internal_display_id = display::test::DisplayManagerTestApi(display_manager()) .SetFirstDisplayAsInternalDisplay(); - constexpr int first_mirror_id = 11; - constexpr int second_mirror_id = 12; + constexpr int64_t first_mirror_id = 11; + constexpr int64_t second_mirror_id = 12; std::vector<display::ManagedDisplayInfo> display_info_list; + display_info_list.push_back(display::CreateDisplayInfo( + internal_display_id, gfx::Rect(0, 0, 500, 500))); display_info_list.push_back( - CreateDisplayInfo(internal_display_id, gfx::Rect(0, 0, 500, 500))); + display::CreateDisplayInfo(first_mirror_id, gfx::Rect(0, 0, 500, 500))); display_info_list.push_back( - CreateDisplayInfo(first_mirror_id, gfx::Rect(0, 0, 500, 500))); - display_info_list.push_back( - CreateDisplayInfo(second_mirror_id, gfx::Rect(0, 0, 500, 500))); + display::CreateDisplayInfo(second_mirror_id, gfx::Rect(0, 0, 500, 500))); // mirrored across 3 displays... display_manager()->OnNativeDisplaysChanged(display_info_list); @@ -3972,16 +3969,16 @@ } TEST_F(MultiMirroringTest, SourceAndDestinationInSoftwareMirrorMode) { - constexpr int first_display_id = 10; - constexpr int second_display_id = 11; - constexpr int third_display_id = 12; + constexpr int64_t first_display_id = 10; + constexpr int64_t second_display_id = 11; + constexpr int64_t third_display_id = 12; std::vector<display::ManagedDisplayInfo> display_info_list; display_info_list.emplace_back( - CreateDisplayInfo(first_display_id, gfx::Rect(0, 0, 100, 100))); + display::CreateDisplayInfo(first_display_id, gfx::Rect(0, 0, 100, 100))); display_info_list.emplace_back( - CreateDisplayInfo(second_display_id, gfx::Rect(1, 1, 500, 500))); + display::CreateDisplayInfo(second_display_id, gfx::Rect(1, 1, 500, 500))); display_info_list.emplace_back( - CreateDisplayInfo(third_display_id, gfx::Rect(2, 2, 500, 500))); + display::CreateDisplayInfo(third_display_id, gfx::Rect(2, 2, 500, 500))); // Connect all displays. display_manager()->OnNativeDisplaysChanged(display_info_list); @@ -4018,15 +4015,15 @@ const int64_t internal_display_id = display::test::DisplayManagerTestApi(display_manager()) .SetFirstDisplayAsInternalDisplay(); - constexpr int first_mirror_id = 11; - constexpr int second_mirror_id = 12; + constexpr int64_t first_mirror_id = 11; + constexpr int64_t second_mirror_id = 12; std::vector<display::ManagedDisplayInfo> display_info_list; + display_info_list.push_back(display::CreateDisplayInfo( + internal_display_id, gfx::Rect(0, 0, 100, 100))); display_info_list.push_back( - CreateDisplayInfo(internal_display_id, gfx::Rect(0, 0, 100, 100))); + display::CreateDisplayInfo(first_mirror_id, gfx::Rect(1, 1, 500, 500))); display_info_list.push_back( - CreateDisplayInfo(first_mirror_id, gfx::Rect(1, 1, 500, 500))); - display_info_list.push_back( - CreateDisplayInfo(second_mirror_id, gfx::Rect(2, 2, 500, 500))); + display::CreateDisplayInfo(second_mirror_id, gfx::Rect(2, 2, 500, 500))); // Connect all displays, cursor compositing is disabled by default. display_manager()->OnNativeDisplaysChanged(display_info_list); @@ -4051,59 +4048,130 @@ EXPECT_EQ(nullptr, test_api.GetCursorWindow()); } -TEST_F(MultiMirroringTest, RestoreMirrorMode) { - constexpr int64_t id1 = 1; - constexpr int64_t id2 = 2; - constexpr int64_t id3 = 3; - std::unique_ptr<display::DisplaySnapshot> snapshot1 = - display::FakeDisplaySnapshot::Builder() - .SetId(id1) - .SetNativeMode(MakeDisplayMode()) - .Build(); - std::unique_ptr<display::DisplaySnapshot> snapshot2 = - display::FakeDisplaySnapshot::Builder() - .SetId(id2) - .SetNativeMode(MakeDisplayMode()) - .SetOrigin({0, 1000}) - .Build(); - std::unique_ptr<display::DisplaySnapshot> snapshot3 = - display::FakeDisplaySnapshot::Builder() - .SetId(id3) - .SetNativeMode(MakeDisplayMode()) - .SetOrigin({0, 2000}) - .Build(); - snapshot1->set_current_mode(snapshot1->native_mode()); - snapshot2->set_current_mode(snapshot2->native_mode()); - snapshot3->set_current_mode(snapshot3->native_mode()); - display::DisplayConfigurator::DisplayStateList outputs; - outputs.push_back(snapshot1.get()); - outputs.push_back(snapshot2.get()); - outputs.push_back(snapshot3.get()); +TEST_F(MultiMirroringTest, MirrorModeRestore) { + const int64_t internal_display_id = + display::test::DisplayManagerTestApi(display_manager()) + .SetFirstDisplayAsInternalDisplay(); + constexpr int64_t first_display_id = 210000001; + constexpr int64_t second_display_id = 220000002; + const int64_t first_display_masked_id = + display::GetDisplayIdWithoutOutputIndex(first_display_id); + const int64_t second_display_masked_id = + display::GetDisplayIdWithoutOutputIndex(second_display_id); + display::ManagedDisplayInfo first_mirror_info = + display::CreateDisplayInfo(first_display_id, gfx::Rect(1, 1, 500, 500)); + display::ManagedDisplayInfo second_mirror_info = + display::CreateDisplayInfo(second_display_id, gfx::Rect(2, 2, 500, 500)); + std::vector<display::ManagedDisplayInfo> display_info_list; - // The default state for display id list is EXTENDED. - display::DisplayChangeObserver observer(Shell::Get()->display_configurator(), - display_manager()); - EXPECT_EQ(display::MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED, - observer.GetStateForDisplayIds(outputs)); - observer.OnDisplayModeChanged(outputs); + // There's no external display now. + display_info_list.push_back(display::CreateDisplayInfo( + internal_display_id, gfx::Rect(0, 0, 100, 100))); + display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_FALSE(display_manager()->IsInMirrorMode()); + EXPECT_TRUE(display_manager()->external_display_mirror_info().empty()); - // Turn on mirror mode. The mirror state is stored. + // Connect the first external display. + display_info_list.push_back(first_mirror_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_FALSE(display_manager()->IsInMirrorMode()); + EXPECT_TRUE(display_manager()->external_display_mirror_info().empty()); + + // Turn on mirror mode. ActivateSoftwareMirrorMode(true); - EXPECT_TRUE(display_manager()->IsInSoftwareMirrorMode()); - EXPECT_EQ(display::MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, - observer.GetStateForDisplayIds(outputs)); + EXPECT_TRUE(display_manager()->IsInMirrorMode()); + EXPECT_EQ(1U, display_manager()->external_display_mirror_info().size()); + EXPECT_TRUE(display_manager()->external_display_mirror_info().count( + first_display_masked_id)); - // Remove one display and turn off mirror mode. - outputs.erase(outputs.end() - 1); - observer.OnDisplayModeChanged(outputs); + // Remove the first external display. + display_info_list.erase(display_info_list.end() - 1); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_FALSE(display_manager()->IsInMirrorMode()); + EXPECT_EQ(1U, display_manager()->external_display_mirror_info().size()); + EXPECT_TRUE(display_manager()->external_display_mirror_info().count( + first_display_masked_id)); + + // Reconnect the first external display. + display_info_list.push_back(first_mirror_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_TRUE(display_manager()->IsInMirrorMode()); + EXPECT_EQ(1U, display_manager()->external_display_mirror_info().size()); + EXPECT_TRUE(display_manager()->external_display_mirror_info().count( + first_display_masked_id)); + + // Remove the first external display. + display_info_list.erase(display_info_list.end() - 1); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_FALSE(display_manager()->IsInMirrorMode()); + EXPECT_EQ(1U, display_manager()->external_display_mirror_info().size()); + EXPECT_TRUE(display_manager()->external_display_mirror_info().count( + first_display_masked_id)); + + // Connect the second external display. + display_info_list.push_back(second_mirror_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_FALSE(display_manager()->IsInMirrorMode()); + EXPECT_EQ(1U, display_manager()->external_display_mirror_info().size()); + EXPECT_TRUE(display_manager()->external_display_mirror_info().count( + first_display_masked_id)); + + // Remove the second external display. + display_info_list.erase(display_info_list.end() - 1); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_FALSE(display_manager()->IsInMirrorMode()); + EXPECT_EQ(1U, display_manager()->external_display_mirror_info().size()); + EXPECT_TRUE(display_manager()->external_display_mirror_info().count( + first_display_masked_id)); + + // Add the first and then add the second external display (not mirrored + // before). + display_info_list.push_back(first_mirror_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); + display_info_list.push_back(second_mirror_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_TRUE(display_manager()->IsInMirrorMode()); + EXPECT_EQ(2U, display_manager()->external_display_mirror_info().size()); + EXPECT_TRUE(display_manager()->external_display_mirror_info().count( + first_display_masked_id)); + EXPECT_TRUE(display_manager()->external_display_mirror_info().count( + second_display_masked_id)); + + // Remove the second display. + display_info_list.erase(display_info_list.end() - 1); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_TRUE(display_manager()->IsInMirrorMode()); + EXPECT_EQ(2U, display_manager()->external_display_mirror_info().size()); + EXPECT_TRUE(display_manager()->external_display_mirror_info().count( + first_display_masked_id)); + EXPECT_TRUE(display_manager()->external_display_mirror_info().count( + second_display_masked_id)); + + // Remove the first display and then add the second display. + display_info_list.erase(display_info_list.end() - 1); + display_manager()->OnNativeDisplaysChanged(display_info_list); + display_info_list.push_back(second_mirror_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_TRUE(display_manager()->IsInMirrorMode()); + EXPECT_EQ(2U, display_manager()->external_display_mirror_info().size()); + EXPECT_TRUE(display_manager()->external_display_mirror_info().count( + first_display_masked_id)); + EXPECT_TRUE(display_manager()->external_display_mirror_info().count( + second_display_masked_id)); + + // Turn off mirror mode. ActivateSoftwareMirrorMode(false); EXPECT_FALSE(display_manager()->IsInMirrorMode()); + EXPECT_EQ(1U, display_manager()->external_display_mirror_info().size()); + EXPECT_TRUE(display_manager()->external_display_mirror_info().count( + first_display_masked_id)); - // Add the display we removed before, the mirror mode is restored. - outputs.push_back(snapshot3.get()); - observer.OnDisplayModeChanged(outputs); - EXPECT_TRUE(display_manager()->IsInSoftwareMirrorMode()); + // Add the first display (mirrored before). + display_info_list.push_back(first_mirror_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_FALSE(display_manager()->IsInMirrorMode()); + EXPECT_FALSE(display_manager()->IsInMirrorMode()); + EXPECT_TRUE(display_manager()->external_display_mirror_info().empty()); } } // namespace ash
diff --git a/ash/display/mirror_window_controller.cc b/ash/display/mirror_window_controller.cc index a5b78916..d957f232 100644 --- a/ash/display/mirror_window_controller.cc +++ b/ash/display/mirror_window_controller.cc
@@ -107,11 +107,20 @@ display::DisplayManager* display_manager = Shell::Get()->display_manager(); return display_manager->IsInUnifiedMode() ? display::DisplayManager::UNIFIED - : (display_manager->IsInMirrorMode() + : (display_manager->IsInSoftwareMirrorMode() ? display::DisplayManager::MIRRORING : display::DisplayManager::EXTENDED); } +int64_t GetCurrentReflectingSourceId() { + display::DisplayManager* display_manager = Shell::Get()->display_manager(); + if (display_manager->IsInUnifiedMode()) + return display::Screen::GetScreen()->GetPrimaryDisplay().id(); + if (display_manager->IsInSoftwareMirrorMode()) + return display_manager->mirroring_source_id(); + return display::kInvalidDisplayId; +} + } // namespace struct MirrorWindowController::MirroringHostInfo { @@ -137,27 +146,26 @@ void MirrorWindowController::UpdateWindow( const std::vector<display::ManagedDisplayInfo>& display_info_list) { - static int mirror_host_count = 0; display::DisplayManager* display_manager = Shell::Get()->display_manager(); - const display::Display& primary = - display::Screen::GetScreen()->GetPrimaryDisplay(); - const display::ManagedDisplayInfo& source_display_info = - display_manager->GetDisplayInfo(primary.id()); + DCHECK(display_manager->IsInSoftwareMirrorMode() || + display_manager->IsInUnifiedMode()); + static int mirror_host_count = 0; multi_display_mode_ = GetCurrentMultiDisplayMode(); + reflecting_source_id_ = GetCurrentReflectingSourceId(); for (const display::ManagedDisplayInfo& display_info : display_info_list) { std::unique_ptr<RootWindowTransformer> transformer; - if (display_manager->IsInMirrorMode()) { + if (display_manager->IsInSoftwareMirrorMode()) { transformer.reset(CreateRootWindowTransformerForMirroredDisplay( - source_display_info, display_info)); - } else if (display_manager->IsInUnifiedMode()) { + display_manager->GetDisplayInfo(reflecting_source_id_), + display_info)); + } else { + DCHECK(display_manager->IsInUnifiedMode()); display::Display display = display_manager->GetMirroringDisplayById(display_info.id()); transformer.reset(CreateRootWindowTransformerForUnifiedDesktop( - primary.bounds(), display)); - } else { - NOTREACHED(); + display::Screen::GetScreen()->GetPrimaryDisplay().bounds(), display)); } if (mirroring_host_info_map_.find(display_info.id()) == @@ -197,7 +205,7 @@ AshWindowTreeHost* unified_ash_host = Shell::Get() ->window_tree_host_manager() - ->GetAshWindowTreeHostForDisplayId(primary.id()); + ->GetAshWindowTreeHostForDisplayId(reflecting_source_id_); unified_ash_host->RegisterMirroringHost(host_info->ash_host.get()); aura::client::SetScreenPositionClient(host->window(), screen_position_client_.get()); @@ -224,7 +232,9 @@ aura::Env::GetInstance() ->context_factory_private() ->CreateReflector( - Shell::GetPrimaryRootWindow()->GetHost()->compositor(), + Shell::GetRootWindowForDisplayId(reflecting_source_id_) + ->GetHost() + ->compositor(), mirror_window->layer()); } } @@ -278,9 +288,10 @@ void MirrorWindowController::CloseIfNotNecessary() { display::DisplayManager::MultiDisplayMode new_mode = GetCurrentMultiDisplayMode(); - if (multi_display_mode_ != new_mode) { + int64_t new_reflecting_source_id = GetCurrentReflectingSourceId(); + if (multi_display_mode_ != new_mode || + reflecting_source_id_ != new_reflecting_source_id) { Close(true); - multi_display_mode_ = new_mode; } else { UpdateWindow(); }
diff --git a/ash/display/mirror_window_controller.h b/ash/display/mirror_window_controller.h index f350df3..5e07030 100644 --- a/ash/display/mirror_window_controller.h +++ b/ash/display/mirror_window_controller.h
@@ -104,6 +104,9 @@ display::DisplayManager::MultiDisplayMode multi_display_mode_; + // The id of the display being mirrored in the reflector. + int64_t reflecting_source_id_ = display::kInvalidDisplayId; + std::unique_ptr<aura::client::ScreenPositionClient> screen_position_client_; std::unique_ptr<ui::Reflector> reflector_;
diff --git a/ash/display/mirror_window_controller_unittest.cc b/ash/display/mirror_window_controller_unittest.cc index 9dbec2e..693128d 100644 --- a/ash/display/mirror_window_controller_unittest.cc +++ b/ash/display/mirror_window_controller_unittest.cc
@@ -66,8 +66,9 @@ aura::test::TestWindowDelegate test_window_delegate; test_window_delegate.set_window_component(HTTOP); - display_manager()->SetMultiDisplayMode(display::DisplayManager::MIRRORING); UpdateDisplay("400x400,400x400"); + display_manager()->SetMirrorMode(true); + RunAllPendingInMessageLoop(); aura::Window* root = Shell::Get()->GetPrimaryRootWindow(); std::unique_ptr<aura::Window> window(aura::test::CreateTestWindowWithDelegate( &test_window_delegate, 0, gfx::Rect(50, 50, 100, 100), root)); @@ -118,8 +119,9 @@ aura::test::TestWindowDelegate test_window_delegate; test_window_delegate.set_window_component(HTTOP); - display_manager()->SetMultiDisplayMode(display::DisplayManager::MIRRORING); UpdateDisplay("400x400,400x400"); + display_manager()->SetMirrorMode(true); + RunAllPendingInMessageLoop(); aura::Window* root = Shell::Get()->GetPrimaryRootWindow(); std::unique_ptr<aura::Window> window(aura::test::CreateTestWindowWithDelegate( &test_window_delegate, 0, gfx::Rect(50, 50, 100, 100), root)); @@ -175,10 +177,11 @@ return; MirrorWindowTestApi test_api; - display_manager()->SetMultiDisplayMode(display::DisplayManager::MIRRORING); // Test with device scale factor. UpdateDisplay("400x600*2,400x600"); + display_manager()->SetMirrorMode(true); + RunAllPendingInMessageLoop(); aura::Window* root = Shell::Get()->GetPrimaryRootWindow(); ui::test::EventGenerator generator(root); @@ -236,8 +239,9 @@ EXPECT_EQ(display::Display::ROTATE_0, cursor_test_api.GetCurrentCursorRotation()); - display_manager()->SetMultiDisplayMode(display::DisplayManager::MIRRORING); UpdateDisplay("400x400*2/r,400x400"); + display_manager()->SetMirrorMode(true); + RunAllPendingInMessageLoop(); // Entering mirror mode should have centered the cursor on the primary display // because the cursor's previous position is out of bounds. @@ -271,8 +275,6 @@ CreateDisplayInfo(external_id, gfx::Rect(1, 1, 100, 100)); std::vector<display::ManagedDisplayInfo> display_info_list; - display_manager()->SetMultiDisplayMode(display::DisplayManager::MIRRORING); - // software mirroring. display_info_list.push_back(internal_display_info); display_info_list.push_back(external_display_info); @@ -282,15 +284,16 @@ .SetFirstDisplayAsInternalDisplay(); EXPECT_EQ(internal_id, internal_display_id); + display_manager()->SetMirrorMode(true); + RunAllPendingInMessageLoop(); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); - EXPECT_TRUE(display_manager()->IsInMirrorMode()); + EXPECT_TRUE(display_manager()->IsInSoftwareMirrorMode()); EXPECT_EQ(external_id, display_manager()->GetMirroringDestinationDisplayIdList()[0]); // dock mode. display_info_list.clear(); display_info_list.push_back(external_display_info); - display_manager()->SetMultiDisplayMode(display::DisplayManager::MIRRORING); display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); EXPECT_FALSE(display_manager()->IsInMirrorMode()); @@ -299,7 +302,6 @@ display_info_list.clear(); display_info_list.push_back(internal_display_info); display_info_list.push_back(external_display_info); - display_manager()->SetMultiDisplayMode(display::DisplayManager::MIRRORING); display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); EXPECT_TRUE(display_manager()->IsInMirrorMode());
diff --git a/ash/display/root_window_transformers_unittest.cc b/ash/display/root_window_transformers_unittest.cc index 4e1a0d4..8129d7cd 100644 --- a/ash/display/root_window_transformers_unittest.cc +++ b/ash/display/root_window_transformers_unittest.cc
@@ -405,8 +405,8 @@ TEST_F(RootWindowTransformersTest, LetterBoxPillarBox) { MirrorWindowTestApi test_api; - display_manager()->SetMultiDisplayMode(display::DisplayManager::MIRRORING); UpdateDisplay("400x200,500x500"); + display_manager()->SetMirrorMode(true); std::unique_ptr<RootWindowTransformer> transformer( CreateCurrentRootWindowTransformerForMirroring()); // Y margin must be margin is (500 - 500/400 * 200) / 2 = 125.
diff --git a/ash/display/touch_calibrator_controller_unittest.cc b/ash/display/touch_calibrator_controller_unittest.cc index 2b4d061..c075223 100644 --- a/ash/display/touch_calibrator_controller_unittest.cc +++ b/ash/display/touch_calibrator_controller_unittest.cc
@@ -11,6 +11,7 @@ #include "ash/test/ash_test_base.h" #include "ash/touch/ash_touch_transform_controller.h" #include "base/stl_util.h" +#include "services/ui/public/cpp/input_devices/input_device_client_test_api.h" #include "ui/display/display.h" #include "ui/display/manager/chromeos/test/touch_device_manager_test_api.h" #include "ui/display/manager/chromeos/test/touch_transform_controller_test_api.h" @@ -19,7 +20,6 @@ #include "ui/display/manager/display_manager.h" #include "ui/display/test/display_manager_test_api.h" #include "ui/events/base_event_utils.h" -#include "ui/events/devices/input_device_manager.h" #include "ui/events/devices/touch_device_transform.h" #include "ui/events/event_handler.h" #include "ui/events/test/event_generator.h" @@ -52,7 +52,7 @@ // Reset all touch device and touch association. test::TouchDeviceManagerTestApi(touch_device_manager()) .ResetTouchDeviceManager(); - ui::InputDeviceManager::GetInstance()->SetTouchscreenDevicesForTesting({}); + ui::InputDeviceClientTestApi().SetTouchscreenDevices({}); test::TouchTransformControllerTestApi( Shell::Get()->touch_transformer_controller()) .touch_transform_setter() @@ -169,8 +169,7 @@ ui::TouchscreenDevice InitTouchDevice( int64_t display_id, const ui::TouchscreenDevice& touchdevice) { - ui::InputDeviceManager::GetInstance()->SetTouchscreenDevicesForTesting( - {touchdevice}); + ui::InputDeviceClientTestApi().SetTouchscreenDevices({touchdevice}); std::vector<ui::TouchDeviceTransform> transforms; ui::TouchDeviceTransform touch_device_transform; @@ -404,7 +403,7 @@ kExternalTouchId, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, std::string("external touch device"), gfx::Size(1000, 1000), 1); - ui::InputDeviceManager::GetInstance()->SetTouchscreenDevicesForTesting( + ui::InputDeviceClientTestApi().SetTouchscreenDevices( {internal_touchdevice, external_touchdevice}); // Associate both touch devices to the internal display. @@ -496,7 +495,7 @@ kExternalTouchId, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, std::string("external touch device"), gfx::Size(1000, 1000), 1); - ui::InputDeviceManager::GetInstance()->SetTouchscreenDevicesForTesting( + ui::InputDeviceClientTestApi().SetTouchscreenDevices( {internal_touchdevice, external_touchdevice}); // Associate both touch devices to the internal display.
diff --git a/ash/fast_ink/fast_ink_view.cc b/ash/fast_ink/fast_ink_view.cc index 69c55cb..5992d49 100644 --- a/ash/fast_ink/fast_ink_view.cc +++ b/ash/fast_ink/fast_ink_view.cc
@@ -426,15 +426,13 @@ gles2->BindTexImage2DCHROMIUM(GL_TEXTURE_2D, resource->image); gpu::SyncToken sync_token; - uint64_t fence_sync = gles2->InsertFenceSyncCHROMIUM(); - gles2->OrderingBarrierCHROMIUM(); // For mus and mash, the compositor isn't sharing the GPU channel with // FastInkView, so it cannot consume unverified sync token generated here. // We need generate verified sync token for mus and mash. if (ash::Shell::GetAshConfig() == ash::Config::CLASSIC) - gles2->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + gles2->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); else - gles2->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + gles2->GenSyncTokenCHROMIUM(sync_token.GetData()); viz::TransferableResource transferable_resource; transferable_resource.id = next_resource_id_++;
diff --git a/ash/login/ui/login_auth_user_view.cc b/ash/login/ui/login_auth_user_view.cc index f9a2b5a..6932460 100644 --- a/ash/login/ui/login_auth_user_view.cc +++ b/ash/login/ui/login_auth_user_view.cc
@@ -145,7 +145,8 @@ // Use views::GridLayout instead of views::BoxLayout because views::BoxLayout // lays out children according to the view->children order. - views::GridLayout* grid_layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* grid_layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); views::ColumnSet* column_set = grid_layout->AddColumnSet(0); column_set->AddColumn(views::GridLayout::CENTER, views::GridLayout::LEADING, 0 /*resize_percent*/, views::GridLayout::USE_PREF,
diff --git a/ash/login/ui/login_user_view.cc b/ash/login/ui/login_user_view.cc index f3ec9481..5cde228 100644 --- a/ash/login/ui/login_user_view.cc +++ b/ash/login/ui/login_user_view.cc
@@ -484,7 +484,8 @@ // Use views::GridLayout instead of views::BoxLayout because views::BoxLayout // lays out children according to the view->children order. - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); constexpr int kImageColumnId = 0; constexpr int kLabelDropdownColumnId = 1;
diff --git a/ash/message_center/notifier_settings_view.cc b/ash/message_center/notifier_settings_view.cc index a4d167f..a5a646a 100644 --- a/ash/message_center/notifier_settings_view.cc +++ b/ash/message_center/notifier_settings_view.cc
@@ -417,7 +417,7 @@ using views::ColumnSet; using views::GridLayout; - GridLayout* layout = GridLayout::CreateAndInstall(this); + GridLayout* layout = SetLayoutManager(std::make_unique<GridLayout>(this)); ColumnSet* cs = layout->AddColumnSet(0); // Add a column for the checkbox. cs->AddPaddingColumn(0, kInnateCheckboxRightPadding);
diff --git a/ash/session/session_aborted_dialog.cc b/ash/session/session_aborted_dialog.cc index a2daf00f..71a23dae 100644 --- a/ash/session/session_aborted_dialog.cc +++ b/ash/session/session_aborted_dialog.cc
@@ -81,7 +81,8 @@ constexpr int kTopInset = 10; constexpr int kOtherInset = 40; // Create the views and layout manager and set them up. - views::GridLayout* grid_layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* grid_layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); SetBorder(views::CreateEmptyBorder(kTopInset, kOtherInset, kOtherInset, kOtherInset));
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc index 898dbf0..9019a482 100644 --- a/ash/shelf/shelf_view.cc +++ b/ash/shelf/shelf_view.cc
@@ -202,6 +202,24 @@ return display::Screen::GetScreen()->GetDisplayNearestWindow(window).id(); } +// Whether |item_view| is a ShelfButton and its state is STATE_DRAGGING. +bool ShelfButtonIsInDrag(const ShelfItemType item_type, + const views::View* item_view) { + switch (item_type) { + case TYPE_PINNED_APP: + case TYPE_BROWSER_SHORTCUT: + case TYPE_APP: + return static_cast<const ShelfButton*>(item_view)->state() & + ShelfButton::STATE_DRAGGING; + case TYPE_DIALOG: + case TYPE_APP_PANEL: + case TYPE_BACK_BUTTON: + case TYPE_APP_LIST: + case TYPE_UNDEFINED: + return false; + } +} + } // namespace // AnimationDelegate used when deleting an item. This steadily decreased the @@ -1861,8 +1879,7 @@ // Only selected shelf items with context menu opened can be dragged. const ShelfItem* item = ShelfItemForView(source); - if (context_menu && item && item->type != TYPE_APP_LIST && - item->type != TYPE_BACK_BUTTON && + if (context_menu && item && ShelfButtonIsInDrag(item->type, source) && source_type == ui::MenuSourceType::MENU_SOURCE_TOUCH) { run_types |= views::MenuRunner::SEND_GESTURE_EVENTS_TO_OWNER; }
diff --git a/ash/shell/shell_delegate_impl.cc b/ash/shell/shell_delegate_impl.cc index 2d971674..65e5edd 100644 --- a/ash/shell/shell_delegate_impl.cc +++ b/ash/shell/shell_delegate_impl.cc
@@ -74,10 +74,6 @@ return new DefaultAccessibilityDelegate; } -base::string16 ShellDelegateImpl::GetProductName() const { - return base::string16(); -} - ui::InputDeviceControllerClient* ShellDelegateImpl::GetInputDeviceControllerClient() { return nullptr;
diff --git a/ash/shell/shell_delegate_impl.h b/ash/shell/shell_delegate_impl.h index 2a30d3e..14b8ea3 100644 --- a/ash/shell/shell_delegate_impl.h +++ b/ash/shell/shell_delegate_impl.h
@@ -36,7 +36,6 @@ std::unique_ptr<ScreenshotDelegate> CreateScreenshotDelegate() override; std::unique_ptr<WallpaperDelegate> CreateWallpaperDelegate() override; AccessibilityDelegate* CreateAccessibilityDelegate() override; - base::string16 GetProductName() const override; ui::InputDeviceControllerClient* GetInputDeviceControllerClient() override; private:
diff --git a/ash/shell/window_type_launcher.cc b/ash/shell/window_type_launcher.cc index c2becff..0bbc8ce 100644 --- a/ash/shell/window_type_launcher.cc +++ b/ash/shell/window_type_launcher.cc
@@ -210,7 +210,8 @@ this, base::ASCIIToUTF16("Show a web/app notification"))), show_views_examples_callback_(show_views_examples_callback) { - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); SetBorder(views::CreateEmptyBorder(gfx::Insets(5))); views::ColumnSet* column_set = layout->AddColumnSet(0); column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
diff --git a/ash/shell_delegate.h b/ash/shell_delegate.h index 62ef39f..a77cace 100644 --- a/ash/shell_delegate.h +++ b/ash/shell_delegate.h
@@ -84,9 +84,6 @@ // Creates a accessibility delegate. Shell takes ownership of the delegate. virtual AccessibilityDelegate* CreateAccessibilityDelegate() = 0; - // Get the product name. - virtual base::string16 GetProductName() const = 0; - virtual void OpenKeyboardShortcutHelpPage() const {} // Creator of Shell owns this; it's assumed this outlives Shell.
diff --git a/ash/shell_delegate_mus.cc b/ash/shell_delegate_mus.cc index 55886b4..ba8959a3 100644 --- a/ash/shell_delegate_mus.cc +++ b/ash/shell_delegate_mus.cc
@@ -104,11 +104,6 @@ return new DefaultAccessibilityDelegate; } -base::string16 ShellDelegateMus::GetProductName() const { - NOTIMPLEMENTED_LOG_ONCE(); - return base::string16(); -} - ui::InputDeviceControllerClient* ShellDelegateMus::GetInputDeviceControllerClient() { if (!connector_)
diff --git a/ash/shell_delegate_mus.h b/ash/shell_delegate_mus.h index 3f2933ee..6869a8e 100644 --- a/ash/shell_delegate_mus.h +++ b/ash/shell_delegate_mus.h
@@ -34,7 +34,6 @@ std::unique_ptr<ScreenshotDelegate> CreateScreenshotDelegate() override; std::unique_ptr<WallpaperDelegate> CreateWallpaperDelegate() override; AccessibilityDelegate* CreateAccessibilityDelegate() override; - base::string16 GetProductName() const override; ui::InputDeviceControllerClient* GetInputDeviceControllerClient() override; private:
diff --git a/ash/system/date/date_view.cc b/ash/system/date/date_view.cc index 7d8e71c..4da30347 100644 --- a/ash/system/date/date_view.cc +++ b/ash/system/date/date_view.cc
@@ -262,7 +262,8 @@ AddChildView(horizontal_label_.get()); } else { RemoveChildView(horizontal_label_.get()); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); const int kColumnId = 0; views::ColumnSet* columns = layout->AddColumnSet(kColumnId); columns->AddPaddingColumn(0, kVerticalClockLeftPadding);
diff --git a/ash/system/ime/tray_ime_chromeos_unittest.cc b/ash/system/ime/tray_ime_chromeos_unittest.cc index 6bf9871..fb533ae 100644 --- a/ash/system/ime/tray_ime_chromeos_unittest.cc +++ b/ash/system/ime/tray_ime_chromeos_unittest.cc
@@ -17,6 +17,7 @@ #include "ash/test/ash_test_base.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" +#include "services/ui/public/cpp/input_devices/input_device_client_test_api.h" #include "ui/events/devices/input_device_manager.h" #include "ui/keyboard/keyboard_util.h" @@ -120,19 +121,21 @@ std::vector<ui::TouchscreenDevice> screens; screens.emplace_back(1, ui::InputDeviceType::INPUT_DEVICE_INTERNAL, "Touchscreen", gfx::Size(1024, 768), 0); - manager->SetTouchscreenDevicesForTesting(screens); + ui::InputDeviceClientTestApi input_device_client_test_api; + input_device_client_test_api.SetTouchscreenDevices(screens); std::vector<ui::InputDevice> keyboards; keyboards.push_back(ui::InputDevice( 2, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, "keyboard")); - manager->SetKeyboardDevicesForTesting(keyboards); + input_device_client_test_api.SetKeyboardDevices(keyboards); } void TrayIMETest::RestoreKeyboard() { DCHECK(keyboard_suppressed_); - ui::InputDeviceManager* manager = ui::InputDeviceManager::GetInstance(); - manager->SetTouchscreenDevicesForTesting(touchscreen_devices_to_restore_); - manager->SetKeyboardDevicesForTesting(keyboard_devices_to_restore_); + ui::InputDeviceClientTestApi().SetTouchscreenDevices( + touchscreen_devices_to_restore_); + ui::InputDeviceClientTestApi().SetKeyboardDevices( + keyboard_devices_to_restore_); } void TrayIMETest::SetUp() {
diff --git a/ash/system/power/peripheral_battery_notifier_unittest.cc b/ash/system/power/peripheral_battery_notifier_unittest.cc index 18b146f0..ea92d8d 100644 --- a/ash/system/power/peripheral_battery_notifier_unittest.cc +++ b/ash/system/power/peripheral_battery_notifier_unittest.cc
@@ -183,7 +183,8 @@ nullptr); } -TEST_F(PeripheralBatteryNotifierTest, StylusNotification) { +// TODO(crbug.com/765794): Flaky on ash_unittests --mus. +TEST_F(PeripheralBatteryNotifierTest, DISABLED_StylusNotification) { const std::string kTestStylusBatteryPath = "/sys/class/power_supply/hid-AAAA:BBBB:CCCC.DDDD-battery"; const std::string kTestStylusName = "test_stylus";
diff --git a/ash/system/screen_layout_observer_unittest.cc b/ash/system/screen_layout_observer_unittest.cc index 73a0642..9c00998 100644 --- a/ash/system/screen_layout_observer_unittest.cc +++ b/ash/system/screen_layout_observer_unittest.cc
@@ -12,6 +12,7 @@ #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/command_line.h" #include "base/strings/string16.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "ui/accessibility/ax_node_data.h" @@ -21,6 +22,8 @@ #include "ui/display/display_layout_builder.h" #include "ui/display/display_switches.h" #include "ui/display/manager/display_manager.h" +#include "ui/display/manager/display_manager_utilities.h" +#include "ui/display/test/display_manager_test_api.h" #include "ui/message_center/message_center.h" #include "ui/message_center/notification.h" #include "ui/message_center/notification_list.h" @@ -184,19 +187,47 @@ GetDisplayNotificationText()); EXPECT_TRUE(GetDisplayNotificationAdditionalText().empty()); - // Mirroring. + const int64_t first_display_id = + display::Screen::GetScreen()->GetPrimaryDisplay().id(); + const int64_t second_display_id = first_display_id + 1; + display::ManagedDisplayInfo first_display_info = + display::CreateDisplayInfo(first_display_id, gfx::Rect(1, 1, 500, 500)); + display::ManagedDisplayInfo second_display_info = + display::CreateDisplayInfo(second_display_id, gfx::Rect(2, 2, 500, 500)); + std::vector<display::ManagedDisplayInfo> display_info_list; + display_info_list.emplace_back(first_display_info); + display_info_list.emplace_back(second_display_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); + + // Turn on mirror mode. CloseNotification(); - display_manager()->SetSoftwareMirroring(true); - UpdateDisplay("400x400,200x200"); + display_manager()->SetMirrorMode(true); EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, GetMirroringDisplayNames()), GetDisplayNotificationText()); EXPECT_TRUE(GetDisplayNotificationAdditionalText().empty()); - // Back to extended. + // Disconnect a display to end mirror mode. CloseNotification(); - display_manager()->SetSoftwareMirroring(false); - UpdateDisplay("400x400,200x200"); + display_info_list.erase(display_info_list.end() - 1); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRROR_EXIT), + GetDisplayNotificationText()); + EXPECT_TRUE(GetDisplayNotificationAdditionalText().empty()); + + // Restore mirror mode. + CloseNotification(); + display_info_list.emplace_back(second_display_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, + GetMirroringDisplayNames()), + GetDisplayNotificationText()); + EXPECT_TRUE(GetDisplayNotificationAdditionalText().empty()); + + // Turn off mirror mode. + CloseNotification(); + display_manager()->SetMirrorMode(false); + display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, GetSecondDisplayName()), GetDisplayNotificationText()); @@ -302,15 +333,14 @@ display_manager()->GetSecondaryDisplay().id()); // Mirroring. - display_manager()->SetSoftwareMirroring(true); UpdateDisplay("400x400,200x200"); + display_manager()->SetMirrorMode(true); EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, GetMirroringDisplayNames()), GetDisplayNotificationText()); // Docked. CloseNotification(); - display_manager()->SetSoftwareMirroring(false); display::Display::SetInternalDisplayId(display_manager()->first_display_id()); UpdateDisplay("200x200"); EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRROR_EXIT), @@ -329,15 +359,14 @@ display_manager()->GetSecondaryDisplay().id()); // Mirroring. - display_manager()->SetSoftwareMirroring(true); UpdateDisplay("400x400,200x200"); + display_manager()->SetMirrorMode(true); EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, GetMirroringDisplayNames()), GetDisplayNotificationText()); // Adding a third display. Mirror mode for 3+ displays is not supported. CloseNotification(); - display_manager()->SetSoftwareMirroring(false); UpdateDisplay("400x400,200x200,100x100"); EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_MIRRORING_NOT_SUPPORTED), GetDisplayNotificationText()); @@ -354,15 +383,14 @@ display_manager()->GetSecondaryDisplay().id()); // Mirroring. - display_manager()->SetSoftwareMirroring(true); UpdateDisplay("400x400,200x200"); + display_manager()->SetMirrorMode(true); EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, GetMirroringDisplayNames()), GetDisplayNotificationText()); // Removing one of the displays. We show that we exited mirror mode. CloseNotification(); - display_manager()->SetSoftwareMirroring(false); UpdateDisplay("400x400"); EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRROR_EXIT), GetDisplayNotificationText()); @@ -531,44 +559,73 @@ }; TEST_F(ScreenLayoutObserverMultiMirroringTest, - ExitMirrorModeBecauseAddOrRemoveDisplayMessage) { + MirrorModeAddOrRemoveDisplayMessage) { Shell::Get()->screen_layout_observer()->set_show_notifications_for_testing( true); - UpdateDisplay("400x400,300x300,200x200"); - display::Display::SetInternalDisplayId( - display_manager()->GetSecondaryDisplay().id()); + + const int64_t internal_display_id = + display::test::DisplayManagerTestApi(display_manager()) + .SetFirstDisplayAsInternalDisplay(); + constexpr int first_display_id = 11; + constexpr int second_display_id = 12; + display::ManagedDisplayInfo first_display_info = + display::CreateDisplayInfo(first_display_id, gfx::Rect(1, 1, 500, 500)); + display::ManagedDisplayInfo second_display_info = + display::CreateDisplayInfo(second_display_id, gfx::Rect(2, 2, 500, 500)); + std::vector<display::ManagedDisplayInfo> display_info_list; + display_info_list.push_back(display::CreateDisplayInfo( + internal_display_id, gfx::Rect(0, 0, 100, 100))); + display_info_list.push_back(first_display_info); + display_info_list.push_back(second_display_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); // Mirroring across 3 displays. - display_manager()->SetSoftwareMirroring(true); - UpdateDisplay("400x400,300x300,200x200"); + display_manager()->SetMirrorMode(true); EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, GetMirroringDisplayNames()), GetDisplayNotificationText()); - // In ChromeOS running on device, mirror mode ends when a display is removed, - // because there's no registered display layout for the updated ID list and - // the mirror mode of the default layout is off. But the test is using - // different code path and the mirror mode persists until it is manually - // turned off, so we simulate to turn off mirror mode when removing the third - // display. + // Mirror mode persists when a display is removed. CloseNotification(); - display_manager()->SetSoftwareMirroring(false); - UpdateDisplay("400x400,300x300"); + display_info_list.erase(display_info_list.end() - 1); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_TRUE(GetDisplayNotificationText().empty()); + EXPECT_TRUE(display_manager()->IsInMirrorMode()); + + // Turn off mirror mode. + CloseNotification(); + display_manager()->SetMirrorMode(false); EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRROR_EXIT), GetDisplayNotificationText()); - // Mirroring across 2 displays. + // Turn on mirror mode. CloseNotification(); - display_manager()->SetSoftwareMirroring(true); - UpdateDisplay("400x400,300x300"); + display_manager()->SetMirrorMode(true); EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, GetMirroringDisplayNames()), GetDisplayNotificationText()); - // Add the third display we removed before, the mirror mode is restored. + // Mirror mode ends when only one display is left. CloseNotification(); - UpdateDisplay("400x400,300x300,200x200"); + display_info_list.erase(display_info_list.end() - 1); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRROR_EXIT), + GetDisplayNotificationText()); + + // Mirror mode is restored when the display is reconncted. + CloseNotification(); + display_info_list.push_back(first_display_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, + GetMirroringDisplayNames()), + GetDisplayNotificationText()); + + // Add the other display, the mirror mode persists. + CloseNotification(); + display_info_list.push_back(second_display_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_TRUE(GetDisplayNotificationText().empty()); + EXPECT_TRUE(display_manager()->IsInMirrorMode()); } } // namespace ash
diff --git a/ash/system/status_area_widget_delegate.cc b/ash/system/status_area_widget_delegate.cc index aa6a6f3e..8b83b4c0b 100644 --- a/ash/system/status_area_widget_delegate.cc +++ b/ash/system/status_area_widget_delegate.cc
@@ -131,7 +131,8 @@ void StatusAreaWidgetDelegate::UpdateLayout() { // Use a grid layout so that the trays can be centered in each cell, and // so that the widget gets laid out correctly when tray sizes change. - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); // Update tray border based on layout. bool is_child_on_edge = true;
diff --git a/ash/system/web_notification/web_notification_tray_unittest.cc b/ash/system/web_notification/web_notification_tray_unittest.cc index f2bab2c..3284a70 100644 --- a/ash/system/web_notification/web_notification_tray_unittest.cc +++ b/ash/system/web_notification/web_notification_tray_unittest.cc
@@ -29,6 +29,7 @@ #include "base/strings/utf_string_conversions.h" #include "ui/display/display.h" #include "ui/display/manager/display_manager.h" +#include "ui/display/manager/display_manager_utilities.h" #include "ui/display/screen.h" #include "ui/events/test/event_generator.h" #include "ui/gfx/geometry/point.h" @@ -252,8 +253,21 @@ TEST_F(WebNotificationTrayTest, PopupShownOnBothDisplays) { Shell::Get()->screen_layout_observer()->set_show_notifications_for_testing( true); - UpdateDisplay("400x400,200x200"); - // UpdateDisplay() creates the display notifications, so popup is visible. + + const int64_t first_display_id = + display::Screen::GetScreen()->GetPrimaryDisplay().id(); + const int64_t second_display_id = first_display_id + 1; + display::ManagedDisplayInfo first_display_info = + display::CreateDisplayInfo(first_display_id, gfx::Rect(1, 1, 500, 500)); + display::ManagedDisplayInfo second_display_info = + display::CreateDisplayInfo(second_display_id, gfx::Rect(2, 2, 500, 500)); + std::vector<display::ManagedDisplayInfo> display_info_list; + display_info_list.emplace_back(first_display_info); + display_info_list.emplace_back(second_display_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); + + // OnNativeDisplaysChanged() creates the display notifications, so popup is + // visible. EXPECT_TRUE(GetTray()->IsPopupVisible()); WebNotificationTray* secondary_tray = GetSecondaryTray(); ASSERT_TRUE(secondary_tray); @@ -264,14 +278,26 @@ // verifies it doesn't cause crash and popups are still visible. See // http://crbug.com/263664 - display_manager()->SetMultiDisplayMode(display::DisplayManager::MIRRORING); - UpdateDisplay("400x400,200x200"); + // Turn on mirror mode. + display_manager()->SetMirrorMode(true); EXPECT_TRUE(GetTray()->IsPopupVisible()); EXPECT_FALSE(GetSecondaryTray()); - display_manager()->SetMultiDisplayMode(display::DisplayManager::EXTENDED); - UpdateDisplay("400x400,200x200"); + // Disconnect a display to end mirror mode. + display_info_list.erase(display_info_list.end() - 1); + display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_TRUE(GetTray()->IsPopupVisible()); + EXPECT_FALSE(GetSecondaryTray()); + + // Restore mirror mode. + display_info_list.emplace_back(second_display_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_TRUE(GetTray()->IsPopupVisible()); + EXPECT_FALSE(GetSecondaryTray()); + + // Turn off mirror mode. + display_manager()->SetMirrorMode(false); + display_manager()->OnNativeDisplaysChanged(display_info_list); secondary_tray = GetSecondaryTray(); ASSERT_TRUE(secondary_tray); EXPECT_TRUE(secondary_tray->IsPopupVisible());
diff --git a/ash/test_shell_delegate.cc b/ash/test_shell_delegate.cc index 28e9560..d8a3f86 100644 --- a/ash/test_shell_delegate.cc +++ b/ash/test_shell_delegate.cc
@@ -62,10 +62,6 @@ return new DefaultAccessibilityDelegate; } -base::string16 TestShellDelegate::GetProductName() const { - return base::string16(); -} - ui::InputDeviceControllerClient* TestShellDelegate::GetInputDeviceControllerClient() { return nullptr;
diff --git a/ash/test_shell_delegate.h b/ash/test_shell_delegate.h index 616a90d..04e980f4 100644 --- a/ash/test_shell_delegate.h +++ b/ash/test_shell_delegate.h
@@ -30,7 +30,6 @@ std::unique_ptr<ScreenshotDelegate> CreateScreenshotDelegate() override; std::unique_ptr<WallpaperDelegate> CreateWallpaperDelegate() override; AccessibilityDelegate* CreateAccessibilityDelegate() override; - base::string16 GetProductName() const override; ui::InputDeviceControllerClient* GetInputDeviceControllerClient() override; void SetForceMaximizeOnFirstRun(bool maximize) {
diff --git a/ash/touch/touch_observer_hud_unittest.cc b/ash/touch/touch_observer_hud_unittest.cc index 98a154a..50f7cc0 100644 --- a/ash/touch/touch_observer_hud_unittest.cc +++ b/ash/touch/touch_observer_hud_unittest.cc
@@ -348,6 +348,10 @@ // Checks if debug touch HUDs are correctly handled when displays are mirrored. TEST_F(TouchHudDebugTest, MirrorDisplays) { + // Disable restoring mirror mode to prevent interference from previous + // display configuration. + display_manager()->set_disable_restoring_mirror_mode_for_test(true); + // Setup a dual display setting. SetupDualDisplays(); @@ -367,11 +371,15 @@ display_manager()->GetSecondaryDisplay().id()); CheckInternalDisplay(); CheckExternalDisplay(); + + display_manager()->set_disable_restoring_mirror_mode_for_test(false); } // Checks if debug touch HUDs are correctly handled when displays are mirrored // after setting the external display as the primary one. TEST_F(TouchHudDebugTest, SwapPrimaryThenMirrorDisplays) { + display_manager()->set_disable_restoring_mirror_mode_for_test(true); + // Setup a dual display setting. SetupDualDisplays(); @@ -395,6 +403,8 @@ display_manager()->GetSecondaryDisplay().id()); CheckInternalDisplay(); CheckExternalDisplay(); + + display_manager()->set_disable_restoring_mirror_mode_for_test(false); } // Checks if debug touch HUDs are correctly handled when the external display,
diff --git a/ash/virtual_keyboard_controller_unittest.cc b/ash/virtual_keyboard_controller_unittest.cc index 52b255b..ffba96c5 100644 --- a/ash/virtual_keyboard_controller_unittest.cc +++ b/ash/virtual_keyboard_controller_unittest.cc
@@ -14,8 +14,8 @@ #include "ash/wm/tablet_mode/scoped_disable_internal_mouse_and_keyboard.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/command_line.h" +#include "services/ui/public/cpp/input_devices/input_device_client_test_api.h" #include "ui/events/devices/input_device.h" -#include "ui/events/devices/input_device_manager.h" #include "ui/events/devices/touchscreen_device.h" #include "ui/keyboard/keyboard_export.h" #include "ui/keyboard/keyboard_switches.h" @@ -28,17 +28,6 @@ VirtualKeyboardControllerTest() = default; ~VirtualKeyboardControllerTest() override = default; - void UpdateTouchscreenDevices( - std::vector<ui::TouchscreenDevice> touchscreen_devices) { - ui::InputDeviceManager::GetInstance()->SetTouchscreenDevicesForTesting( - touchscreen_devices); - } - - void UpdateKeyboardDevices(std::vector<ui::InputDevice> keyboard_devices) { - ui::InputDeviceManager::GetInstance()->SetKeyboardDevicesForTesting( - keyboard_devices); - } - // Sets the event blocker on the maximized window controller. void SetEventBlocker( std::unique_ptr<ScopedDisableInternalMouseAndKeyboard> blocker) { @@ -47,8 +36,8 @@ void SetUp() override { AshTestBase::SetUp(); - UpdateKeyboardDevices(std::vector<ui::InputDevice>()); - UpdateTouchscreenDevices(std::vector<ui::TouchscreenDevice>()); + ui::InputDeviceClientTestApi().SetKeyboardDevices({}); + ui::InputDeviceClientTestApi().SetTouchscreenDevices({}); } private: @@ -64,8 +53,7 @@ std::vector<ui::InputDevice> keyboard_devices; keyboard_devices.push_back(ui::InputDevice( 1, ui::InputDeviceType::INPUT_DEVICE_INTERNAL, "keyboard")); - ui::InputDeviceManager::GetInstance()->SetKeyboardDevicesForTesting( - keyboard_devices); + ui::InputDeviceClientTestApi().SetKeyboardDevices(keyboard_devices); } private: @@ -92,8 +80,8 @@ AshTestBase::SetUp(); // Set the current list of devices to empty so that they don't interfere // with the test. - UpdateKeyboardDevices(std::vector<ui::InputDevice>()); - UpdateTouchscreenDevices(std::vector<ui::TouchscreenDevice>()); + ui::InputDeviceClientTestApi().SetKeyboardDevices({}); + ui::InputDeviceClientTestApi().SetTouchscreenDevices({}); Shell::Get()->system_tray_notifier()->AddVirtualKeyboardObserver(this); } @@ -133,17 +121,17 @@ screens.push_back( ui::TouchscreenDevice(1, ui::InputDeviceType::INPUT_DEVICE_INTERNAL, "Touchscreen", gfx::Size(1024, 768), 0)); - UpdateTouchscreenDevices(screens); + ui::InputDeviceClientTestApi().SetTouchscreenDevices(screens); std::vector<ui::InputDevice> keyboard_devices; keyboard_devices.push_back(ui::InputDevice( 1, ui::InputDeviceType::INPUT_DEVICE_INTERNAL, "keyboard")); - UpdateKeyboardDevices(keyboard_devices); + ui::InputDeviceClientTestApi().SetKeyboardDevices(keyboard_devices); ASSERT_FALSE(keyboard::IsKeyboardEnabled()); // Remove the internal keyboard. Virtual keyboard should now show. - UpdateKeyboardDevices(std::vector<ui::InputDevice>()); + ui::InputDeviceClientTestApi().SetKeyboardDevices({}); EXPECT_TRUE(keyboard::IsKeyboardEnabled()); // Replug in the internal keyboard. Virtual keyboard should hide. - UpdateKeyboardDevices(keyboard_devices); + ui::InputDeviceClientTestApi().SetKeyboardDevices(keyboard_devices); EXPECT_FALSE(keyboard::IsKeyboardEnabled()); } @@ -153,10 +141,10 @@ devices.push_back( ui::TouchscreenDevice(1, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, "Touchscreen", gfx::Size(800, 600), 0)); - UpdateTouchscreenDevices(devices); + ui::InputDeviceClientTestApi().SetTouchscreenDevices(devices); EXPECT_TRUE(keyboard::IsKeyboardEnabled()); // Remove touchscreen. Keyboard should hide. - UpdateTouchscreenDevices(std::vector<ui::TouchscreenDevice>()); + ui::InputDeviceClientTestApi().SetTouchscreenDevices({}); EXPECT_FALSE(keyboard::IsKeyboardEnabled()); } @@ -165,11 +153,11 @@ screens.push_back(ui::TouchscreenDevice( 1, ui::InputDeviceType::INPUT_DEVICE_INTERNAL, "Touchscreen", gfx::Size(1024, 768), 0, false /* has_stylus */)); - UpdateTouchscreenDevices(screens); + ui::InputDeviceClientTestApi().SetTouchscreenDevices(screens); std::vector<ui::InputDevice> keyboard_devices; keyboard_devices.push_back(ui::InputDevice( 1, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, "keyboard")); - UpdateKeyboardDevices(keyboard_devices); + ui::InputDeviceClientTestApi().SetKeyboardDevices(keyboard_devices); ASSERT_FALSE(keyboard::IsKeyboardEnabled()); ASSERT_TRUE(notified()); ASSERT_TRUE(IsVirtualKeyboardSuppressed()); @@ -188,7 +176,7 @@ // Remove external keyboard. Should be notified that the keyboard is not // suppressed. ResetObserver(); - UpdateKeyboardDevices(std::vector<ui::InputDevice>()); + ui::InputDeviceClientTestApi().SetKeyboardDevices({}); ASSERT_TRUE(keyboard::IsKeyboardEnabled()); ASSERT_TRUE(notified()); ASSERT_FALSE(IsVirtualKeyboardSuppressed()); @@ -203,7 +191,7 @@ 2, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, "keyboard")); keyboards.push_back(ui::InputDevice( 3, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, "keyboard")); - UpdateKeyboardDevices(keyboards); + ui::InputDeviceClientTestApi().SetKeyboardDevices(keyboards); ASSERT_FALSE(keyboard::IsKeyboardEnabled()); } @@ -213,11 +201,11 @@ screens.push_back( ui::TouchscreenDevice(1, ui::InputDeviceType::INPUT_DEVICE_INTERNAL, "Touchscreen", gfx::Size(1024, 768), 0)); - UpdateTouchscreenDevices(screens); + ui::InputDeviceClientTestApi().SetTouchscreenDevices(screens); std::vector<ui::InputDevice> keyboard_devices; keyboard_devices.push_back(ui::InputDevice( 1, ui::InputDeviceType::INPUT_DEVICE_INTERNAL, "Keyboard")); - UpdateKeyboardDevices(keyboard_devices); + ui::InputDeviceClientTestApi().SetKeyboardDevices(keyboard_devices); ASSERT_FALSE(keyboard::IsKeyboardEnabled()); // Toggle tablet mode on. Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true); @@ -233,13 +221,13 @@ screens.push_back( ui::TouchscreenDevice(1, ui::InputDeviceType::INPUT_DEVICE_INTERNAL, "Touchscreen", gfx::Size(1024, 768), 0)); - UpdateTouchscreenDevices(screens); + ui::InputDeviceClientTestApi().SetTouchscreenDevices(screens); std::vector<ui::InputDevice> keyboard_devices; keyboard_devices.push_back(ui::InputDevice( 1, ui::InputDeviceType::INPUT_DEVICE_INTERNAL, "Keyboard")); keyboard_devices.push_back(ui::InputDevice( 2, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, "Keyboard")); - UpdateKeyboardDevices(keyboard_devices); + ui::InputDeviceClientTestApi().SetKeyboardDevices(keyboard_devices); // Toggle tablet mode on. Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true); ASSERT_FALSE(keyboard::IsKeyboardEnabled()); @@ -261,7 +249,7 @@ // suppressed. ResetObserver(); keyboard_devices.pop_back(); - UpdateKeyboardDevices(keyboard_devices); + ui::InputDeviceClientTestApi().SetKeyboardDevices(keyboard_devices); ASSERT_TRUE(keyboard::IsKeyboardEnabled()); ASSERT_TRUE(notified()); ASSERT_FALSE(IsVirtualKeyboardSuppressed()); @@ -294,11 +282,11 @@ screens.push_back( ui::TouchscreenDevice(1, ui::InputDeviceType::INPUT_DEVICE_INTERNAL, "Touchscreen", gfx::Size(1024, 768), 0)); - UpdateTouchscreenDevices(screens); + ui::InputDeviceClientTestApi().SetTouchscreenDevices(screens); std::vector<ui::InputDevice> keyboard_devices; keyboard_devices.push_back(ui::InputDevice( 1, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, "keyboard")); - UpdateKeyboardDevices(keyboard_devices); + ui::InputDeviceClientTestApi().SetKeyboardDevices(keyboard_devices); ASSERT_TRUE(keyboard::IsKeyboardEnabled()); }
diff --git a/ash/wm/workspace/workspace_layout_manager.cc b/ash/wm/workspace/workspace_layout_manager.cc index dd5a2d3..2c8e596 100644 --- a/ash/wm/workspace/workspace_layout_manager.cc +++ b/ash/wm/workspace/workspace_layout_manager.cc
@@ -145,15 +145,8 @@ ////////////////////////////////////////////////////////////////////////////// // WorkspaceLayoutManager, keyboard::KeyboardControllerObserver implementation: -void WorkspaceLayoutManager::OnKeyboardBoundsChanging( +void WorkspaceLayoutManager::OnKeyboardWorkspaceDisplacingBoundsChanging( const gfx::Rect& new_bounds) { - // If the keyboard is in sticky mode, change the work area. - const bool change_work_area = - keyboard::KeyboardController::GetInstance() && - keyboard::KeyboardController::GetInstance()->keyboard_locked(); - if (!change_work_area) - return; - aura::Window* window = wm::GetActiveWindow(); if (!window) return;
diff --git a/ash/wm/workspace/workspace_layout_manager.h b/ash/wm/workspace/workspace_layout_manager.h index 840aef9d8..2a39738 100644 --- a/ash/wm/workspace/workspace_layout_manager.h +++ b/ash/wm/workspace/workspace_layout_manager.h
@@ -85,7 +85,8 @@ aura::Window* lost_active) override; // keyboard::KeyboardControllerObserver overrides: - void OnKeyboardBoundsChanging(const gfx::Rect& new_bounds) override; + void OnKeyboardWorkspaceDisplacingBoundsChanging( + const gfx::Rect& new_bounds) override; void OnKeyboardClosed() override; // WindowStateObserver overrides:
diff --git a/ash/wm/workspace/workspace_layout_manager_unittest.cc b/ash/wm/workspace/workspace_layout_manager_unittest.cc index 0b57bb0..dd20141 100644 --- a/ash/wm/workspace/workspace_layout_manager_unittest.cc +++ b/ash/wm/workspace/workspace_layout_manager_unittest.cc
@@ -1552,7 +1552,8 @@ } void ShowKeyboard() { - layout_manager_->OnKeyboardBoundsChanging(keyboard_bounds_); + layout_manager_->OnKeyboardWorkspaceDisplacingBoundsChanging( + keyboard_bounds_); restore_work_area_insets_ = GetPrimaryDisplay().GetWorkAreaInsets(); Shell::Get()->SetDisplayWorkAreaInsets( Shell::GetPrimaryRootWindow(), @@ -1562,7 +1563,7 @@ void HideKeyboard() { Shell::Get()->SetDisplayWorkAreaInsets(Shell::GetPrimaryRootWindow(), restore_work_area_insets_); - layout_manager_->OnKeyboardBoundsChanging(gfx::Rect()); + layout_manager_->OnKeyboardWorkspaceDisplacingBoundsChanging(gfx::Rect()); } // Initializes the keyboard bounds using the bottom half of the work area.
diff --git a/base/files/file_util.h b/base/files/file_util.h index 950d24b..2ebb7378 100644 --- a/base/files/file_util.h +++ b/base/files/file_util.h
@@ -130,6 +130,12 @@ const FilePath& to_path, bool recursive); +// Like CopyDirectory() except trying to overwrite an existing file will not +// work and will return false. +BASE_EXPORT bool CopyDirectoryExcl(const FilePath& from_path, + const FilePath& to_path, + bool recursive); + // Returns true if the given path exists on the local filesystem, // false otherwise. BASE_EXPORT bool PathExists(const FilePath& path);
diff --git a/base/files/file_util_posix.cc b/base/files/file_util_posix.cc index 447ff50..8971b7e 100644 --- a/base/files/file_util_posix.cc +++ b/base/files/file_util_posix.cc
@@ -219,6 +219,148 @@ NOTREACHED(); return false; } + +bool DoCopyDirectory(const FilePath& from_path, + const FilePath& to_path, + bool recursive, + bool open_exclusive) { + AssertBlockingAllowed(); + // Some old callers of CopyDirectory want it to support wildcards. + // After some discussion, we decided to fix those callers. + // Break loudly here if anyone tries to do this. + DCHECK(to_path.value().find('*') == std::string::npos); + DCHECK(from_path.value().find('*') == std::string::npos); + + if (from_path.value().size() >= PATH_MAX) { + return false; + } + + // This function does not properly handle destinations within the source + FilePath real_to_path = to_path; + if (PathExists(real_to_path)) { + real_to_path = MakeAbsoluteFilePath(real_to_path); + if (real_to_path.empty()) + return false; + } else { + real_to_path = MakeAbsoluteFilePath(real_to_path.DirName()); + if (real_to_path.empty()) + return false; + } + FilePath real_from_path = MakeAbsoluteFilePath(from_path); + if (real_from_path.empty()) + return false; + if (real_to_path == real_from_path || real_from_path.IsParent(real_to_path)) + return false; + + int traverse_type = FileEnumerator::FILES | FileEnumerator::SHOW_SYM_LINKS; + if (recursive) + traverse_type |= FileEnumerator::DIRECTORIES; + FileEnumerator traversal(from_path, recursive, traverse_type); + + // We have to mimic windows behavior here. |to_path| may not exist yet, + // start the loop with |to_path|. + struct stat from_stat; + FilePath current = from_path; + if (stat(from_path.value().c_str(), &from_stat) < 0) { + DPLOG(ERROR) << "CopyDirectory() couldn't stat source directory: " + << from_path.value(); + return false; + } + FilePath from_path_base = from_path; + if (recursive && DirectoryExists(to_path)) { + // If the destination already exists and is a directory, then the + // top level of source needs to be copied. + from_path_base = from_path.DirName(); + } + + // The Windows version of this function assumes that non-recursive calls + // will always have a directory for from_path. + // TODO(maruel): This is not necessary anymore. + DCHECK(recursive || S_ISDIR(from_stat.st_mode)); + + do { + // current is the source path, including from_path, so append + // the suffix after from_path to to_path to create the target_path. + FilePath target_path(to_path); + if (from_path_base != current && + !from_path_base.AppendRelativePath(current, &target_path)) { + return false; + } + + if (S_ISDIR(from_stat.st_mode)) { + mode_t mode = (from_stat.st_mode & 01777) | S_IRUSR | S_IXUSR | S_IWUSR; + if (mkdir(target_path.value().c_str(), mode) == 0) + continue; + if (errno == EEXIST && !open_exclusive) + continue; + + DPLOG(ERROR) << "CopyDirectory() couldn't create directory: " + << target_path.value(); + return false; + } + + if (!S_ISREG(from_stat.st_mode)) { + DLOG(WARNING) << "CopyDirectory() skipping non-regular file: " + << current.value(); + continue; + } + + // Add O_NONBLOCK so we can't block opening a pipe. + base::File infile(open(current.value().c_str(), O_RDONLY | O_NONBLOCK)); + if (!infile.IsValid()) { + DPLOG(ERROR) << "CopyDirectory() couldn't open file: " << current.value(); + return false; + } + + struct stat stat_at_use; + if (fstat(infile.GetPlatformFile(), &stat_at_use) < 0) { + DPLOG(ERROR) << "CopyDirectory() couldn't stat file: " << current.value(); + return false; + } + + if (!S_ISREG(stat_at_use.st_mode)) { + DLOG(WARNING) << "CopyDirectory() skipping non-regular file: " + << current.value(); + continue; + } + + int open_flags = O_WRONLY | O_CREAT; + // If |open_exclusive| is set then we should always create the destination + // file, so O_NONBLOCK is not necessary to ensure we don't block on the + // open call for the target file below, and since the destination will + // always be a regular file it wouldn't affect the behavior of the + // subsequent write calls anyway. + if (open_exclusive) + open_flags |= O_EXCL; + else + open_flags |= O_TRUNC | O_NONBLOCK; + // Each platform has different default file opening modes for CopyFile which + // we want to replicate here. On OS X, we use copyfile(3) which takes the + // source file's permissions into account. On the other platforms, we just + // use the base::File constructor. On Chrome OS, base::File uses a different + // set of permissions than it does on other POSIX platforms. +#if defined(OS_MACOSX) + int mode = 0600 | (stat_at_use.st_mode & 0177); +#elif defined(OS_CHROMEOS) + int mode = 0644; +#else + int mode = 0600; +#endif + base::File outfile(open(target_path.value().c_str(), open_flags, mode)); + if (!outfile.IsValid()) { + DPLOG(ERROR) << "CopyDirectory() couldn't create file: " + << target_path.value(); + return false; + } + + if (!CopyFileContents(&infile, &outfile)) { + DLOG(ERROR) << "CopyDirectory() couldn't copy file: " << current.value(); + return false; + } + } while (AdvanceEnumeratorWithStat(&traversal, ¤t, &from_stat)); + + return true; +} #endif // !defined(OS_NACL_NONSFI) #if !defined(OS_MACOSX) @@ -298,135 +440,13 @@ bool CopyDirectory(const FilePath& from_path, const FilePath& to_path, bool recursive) { - AssertBlockingAllowed(); - // Some old callers of CopyDirectory want it to support wildcards. - // After some discussion, we decided to fix those callers. - // Break loudly here if anyone tries to do this. - DCHECK(to_path.value().find('*') == std::string::npos); - DCHECK(from_path.value().find('*') == std::string::npos); + return DoCopyDirectory(from_path, to_path, recursive, false); +} - if (from_path.value().size() >= PATH_MAX) { - return false; - } - - // This function does not properly handle destinations within the source - FilePath real_to_path = to_path; - if (PathExists(real_to_path)) { - real_to_path = MakeAbsoluteFilePath(real_to_path); - if (real_to_path.empty()) - return false; - } else { - real_to_path = MakeAbsoluteFilePath(real_to_path.DirName()); - if (real_to_path.empty()) - return false; - } - FilePath real_from_path = MakeAbsoluteFilePath(from_path); - if (real_from_path.empty()) - return false; - if (real_to_path == real_from_path || real_from_path.IsParent(real_to_path)) - return false; - - int traverse_type = FileEnumerator::FILES | FileEnumerator::SHOW_SYM_LINKS; - if (recursive) - traverse_type |= FileEnumerator::DIRECTORIES; - FileEnumerator traversal(from_path, recursive, traverse_type); - - // We have to mimic windows behavior here. |to_path| may not exist yet, - // start the loop with |to_path|. - struct stat from_stat; - FilePath current = from_path; - if (stat(from_path.value().c_str(), &from_stat) < 0) { - DPLOG(ERROR) << "CopyDirectory() couldn't stat source directory: " - << from_path.value(); - return false; - } - FilePath from_path_base = from_path; - if (recursive && DirectoryExists(to_path)) { - // If the destination already exists and is a directory, then the - // top level of source needs to be copied. - from_path_base = from_path.DirName(); - } - - // The Windows version of this function assumes that non-recursive calls - // will always have a directory for from_path. - // TODO(maruel): This is not necessary anymore. - DCHECK(recursive || S_ISDIR(from_stat.st_mode)); - - do { - // current is the source path, including from_path, so append - // the suffix after from_path to to_path to create the target_path. - FilePath target_path(to_path); - if (from_path_base != current && - !from_path_base.AppendRelativePath(current, &target_path)) { - return false; - } - - if (S_ISDIR(from_stat.st_mode)) { - if (mkdir(target_path.value().c_str(), - (from_stat.st_mode & 01777) | S_IRUSR | S_IXUSR | S_IWUSR) == - 0 || - errno == EEXIST) { - continue; - } - - DPLOG(ERROR) << "CopyDirectory() couldn't create directory: " - << target_path.value(); - return false; - } - - if (!S_ISREG(from_stat.st_mode)) { - DLOG(WARNING) << "CopyDirectory() skipping non-regular file: " - << current.value(); - continue; - } - - // Add O_NONBLOCK so we can't block opening a pipe. - base::File infile(open(current.value().c_str(), O_RDONLY | O_NONBLOCK)); - if (!infile.IsValid()) { - DPLOG(ERROR) << "CopyDirectory() couldn't open file: " << current.value(); - return false; - } - - struct stat stat_at_use; - if (fstat(infile.GetPlatformFile(), &stat_at_use) < 0) { - DPLOG(ERROR) << "CopyDirectory() couldn't stat file: " << current.value(); - return false; - } - - if (!S_ISREG(stat_at_use.st_mode)) { - DLOG(WARNING) << "CopyDirectory() skipping non-regular file: " - << current.value(); - continue; - } - - // Each platform has different default file opening modes for CopyFile which - // we want to replicate here. On OS X, we use copyfile(3) which takes the - // source file's permissions into account. On the other platforms, we just - // use the base::File constructor. On Chrome OS, base::File uses a different - // set of permissions than it does on other POSIX platforms. -#if defined(OS_MACOSX) - int mode = 0600 | (stat_at_use.st_mode & 0177); -#elif defined(OS_CHROMEOS) - int mode = 0644; -#else - int mode = 0600; -#endif - base::File outfile( - open(target_path.value().c_str(), - O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, mode)); - if (!outfile.IsValid()) { - DPLOG(ERROR) << "CopyDirectory() couldn't create file: " - << target_path.value(); - return false; - } - - if (!CopyFileContents(&infile, &outfile)) { - DLOG(ERROR) << "CopyDirectory() couldn't copy file: " << current.value(); - return false; - } - } while (AdvanceEnumeratorWithStat(&traversal, ¤t, &from_stat)); - - return true; +bool CopyDirectoryExcl(const FilePath& from_path, + const FilePath& to_path, + bool recursive) { + return DoCopyDirectory(from_path, to_path, recursive, true); } #endif // !defined(OS_NACL_NONSFI)
diff --git a/base/files/file_util_unittest.cc b/base/files/file_util_unittest.cc index 2545cd5b..ae93125 100644 --- a/base/files/file_util_unittest.cc +++ b/base/files/file_util_unittest.cc
@@ -1051,6 +1051,92 @@ EXPECT_EQ(0777, mode); } +TEST_F(FileUtilTest, CopyDirectoryExclDoesNotOverwrite) { + // Create source directory. + FilePath dir_name_from = + temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir")); + CreateDirectory(dir_name_from); + ASSERT_TRUE(PathExists(dir_name_from)); + + // Create a file under the directory. + FilePath file_name_from = + dir_name_from.Append(FILE_PATH_LITERAL("Reggy-1.txt")); + CreateTextFile(file_name_from, L"Mordecai"); + ASSERT_TRUE(PathExists(file_name_from)); + + // Create destination directory. + FilePath dir_name_to = + temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir")); + CreateDirectory(dir_name_to); + ASSERT_TRUE(PathExists(dir_name_to)); + + // Create a file under the directory with the same name. + FilePath file_name_to = dir_name_to.Append(FILE_PATH_LITERAL("Reggy-1.txt")); + CreateTextFile(file_name_to, L"Rigby"); + ASSERT_TRUE(PathExists(file_name_to)); + + // Ensure that copying failed and the file was not overwritten. + EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false)); + ASSERT_TRUE(PathExists(file_name_to)); + ASSERT_EQ(L"Rigby", ReadTextFile(file_name_to)); +} + +TEST_F(FileUtilTest, CopyDirectoryExclDirectoryOverExistingFile) { + // Create source directory. + FilePath dir_name_from = + temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir")); + CreateDirectory(dir_name_from); + ASSERT_TRUE(PathExists(dir_name_from)); + + // Create a subdirectory. + FilePath subdir_name_from = dir_name_from.Append(FILE_PATH_LITERAL("Subsub")); + CreateDirectory(subdir_name_from); + ASSERT_TRUE(PathExists(subdir_name_from)); + + // Create destination directory. + FilePath dir_name_to = + temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir")); + CreateDirectory(dir_name_to); + ASSERT_TRUE(PathExists(dir_name_to)); + + // Create a regular file under the directory with the same name. + FilePath file_name_to = dir_name_to.Append(FILE_PATH_LITERAL("Subsub")); + CreateTextFile(file_name_to, L"Rigby"); + ASSERT_TRUE(PathExists(file_name_to)); + + // Ensure that copying failed and the file was not overwritten. + EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false)); + ASSERT_TRUE(PathExists(file_name_to)); + ASSERT_EQ(L"Rigby", ReadTextFile(file_name_to)); +} + +TEST_F(FileUtilTest, CopyDirectoryExclDirectoryOverExistingDirectory) { + // Create source directory. + FilePath dir_name_from = + temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir")); + CreateDirectory(dir_name_from); + ASSERT_TRUE(PathExists(dir_name_from)); + + // Create a subdirectory. + FilePath subdir_name_from = dir_name_from.Append(FILE_PATH_LITERAL("Subsub")); + CreateDirectory(subdir_name_from); + ASSERT_TRUE(PathExists(subdir_name_from)); + + // Create destination directory. + FilePath dir_name_to = + temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir")); + CreateDirectory(dir_name_to); + ASSERT_TRUE(PathExists(dir_name_to)); + + // Create a subdirectory under the directory with the same name. + FilePath subdir_name_to = dir_name_to.Append(FILE_PATH_LITERAL("Subsub")); + CreateDirectory(subdir_name_to); + ASSERT_TRUE(PathExists(subdir_name_to)); + + // Ensure that copying failed and the file was not overwritten. + EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false)); +} + TEST_F(FileUtilTest, CopyFileExecutablePermission) { FilePath src = temp_dir_.GetPath().Append(FPL("src.txt")); const std::wstring file_contents(L"Gooooooooooooooooooooogle"); @@ -1782,6 +1868,24 @@ EXPECT_TRUE(PathExists(file_name_to)); } +TEST_F(FileUtilTest, CopyFileFailureWithCopyDirectoryExcl) { + // Create a file + FilePath file_name_from = + temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_Test_File.txt")); + CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle"); + ASSERT_TRUE(PathExists(file_name_from)); + + // Make a destination file. + FilePath file_name_to = temp_dir_.GetPath().Append( + FILE_PATH_LITERAL("Copy_Test_File_Destination.txt")); + CreateTextFile(file_name_to, L"Old file content"); + ASSERT_TRUE(PathExists(file_name_to)); + + // Overwriting the destination should fail. + EXPECT_FALSE(CopyDirectoryExcl(file_name_from, file_name_to, true)); + EXPECT_EQ(L"Old file content", ReadTextFile(file_name_to)); +} + TEST_F(FileUtilTest, CopyDirectoryWithTrailingSeparators) { // Create a directory. FilePath dir_name_from = @@ -1869,6 +1973,169 @@ EXPECT_FALSE(PathExists(symlink_name_to)); EXPECT_FALSE(PathExists(fifo_name_to)); } + +TEST_F(FileUtilTest, CopyDirectoryExclFileOverSymlink) { + // Create a directory. + FilePath dir_name_from = + temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir")); + ASSERT_TRUE(CreateDirectory(dir_name_from)); + ASSERT_TRUE(PathExists(dir_name_from)); + + // Create a file under the directory. + FilePath file_name_from = + dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt")); + CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle"); + ASSERT_TRUE(PathExists(file_name_from)); + + // Create a destination directory with a symlink of the same name. + FilePath dir_name_to = + temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir")); + ASSERT_TRUE(CreateDirectory(dir_name_to)); + ASSERT_TRUE(PathExists(dir_name_to)); + + FilePath symlink_target = + dir_name_to.Append(FILE_PATH_LITERAL("Symlink_Target.txt")); + CreateTextFile(symlink_target, L"asdf"); + ASSERT_TRUE(PathExists(symlink_target)); + + FilePath symlink_name_to = + dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt")); + ASSERT_TRUE(CreateSymbolicLink(symlink_target, symlink_name_to)); + ASSERT_TRUE(PathExists(symlink_name_to)); + + // Check that copying fails. + EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false)); +} + +TEST_F(FileUtilTest, CopyDirectoryExclDirectoryOverSymlink) { + // Create a directory. + FilePath dir_name_from = + temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir")); + ASSERT_TRUE(CreateDirectory(dir_name_from)); + ASSERT_TRUE(PathExists(dir_name_from)); + + // Create a subdirectory. + FilePath subdir_name_from = dir_name_from.Append(FILE_PATH_LITERAL("Subsub")); + CreateDirectory(subdir_name_from); + ASSERT_TRUE(PathExists(subdir_name_from)); + + // Create a destination directory with a symlink of the same name. + FilePath dir_name_to = + temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir")); + ASSERT_TRUE(CreateDirectory(dir_name_to)); + ASSERT_TRUE(PathExists(dir_name_to)); + + FilePath symlink_target = dir_name_to.Append(FILE_PATH_LITERAL("Subsub")); + CreateTextFile(symlink_target, L"asdf"); + ASSERT_TRUE(PathExists(symlink_target)); + + FilePath symlink_name_to = + dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt")); + ASSERT_TRUE(CreateSymbolicLink(symlink_target, symlink_name_to)); + ASSERT_TRUE(PathExists(symlink_name_to)); + + // Check that copying fails. + EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false)); +} + +TEST_F(FileUtilTest, CopyDirectoryExclFileOverDanglingSymlink) { + // Create a directory. + FilePath dir_name_from = + temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir")); + ASSERT_TRUE(CreateDirectory(dir_name_from)); + ASSERT_TRUE(PathExists(dir_name_from)); + + // Create a file under the directory. + FilePath file_name_from = + dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt")); + CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle"); + ASSERT_TRUE(PathExists(file_name_from)); + + // Create a destination directory with a dangling symlink of the same name. + FilePath dir_name_to = + temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir")); + ASSERT_TRUE(CreateDirectory(dir_name_to)); + ASSERT_TRUE(PathExists(dir_name_to)); + + FilePath symlink_target = + dir_name_to.Append(FILE_PATH_LITERAL("Symlink_Target.txt")); + CreateTextFile(symlink_target, L"asdf"); + ASSERT_TRUE(PathExists(symlink_target)); + + FilePath symlink_name_to = + dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt")); + ASSERT_TRUE(CreateSymbolicLink(symlink_target, symlink_name_to)); + ASSERT_TRUE(PathExists(symlink_name_to)); + ASSERT_TRUE(DeleteFile(symlink_target, false)); + + // Check that copying fails and that no file was created for the symlink's + // referent. + EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false)); + EXPECT_FALSE(PathExists(symlink_target)); +} + +TEST_F(FileUtilTest, CopyDirectoryExclDirectoryOverDanglingSymlink) { + // Create a directory. + FilePath dir_name_from = + temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir")); + ASSERT_TRUE(CreateDirectory(dir_name_from)); + ASSERT_TRUE(PathExists(dir_name_from)); + + // Create a subdirectory. + FilePath subdir_name_from = dir_name_from.Append(FILE_PATH_LITERAL("Subsub")); + CreateDirectory(subdir_name_from); + ASSERT_TRUE(PathExists(subdir_name_from)); + + // Create a destination directory with a dangling symlink of the same name. + FilePath dir_name_to = + temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir")); + ASSERT_TRUE(CreateDirectory(dir_name_to)); + ASSERT_TRUE(PathExists(dir_name_to)); + + FilePath symlink_target = + dir_name_to.Append(FILE_PATH_LITERAL("Symlink_Target.txt")); + CreateTextFile(symlink_target, L"asdf"); + ASSERT_TRUE(PathExists(symlink_target)); + + FilePath symlink_name_to = + dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt")); + ASSERT_TRUE(CreateSymbolicLink(symlink_target, symlink_name_to)); + ASSERT_TRUE(PathExists(symlink_name_to)); + ASSERT_TRUE(DeleteFile(symlink_target, false)); + + // Check that copying fails and that no directory was created for the + // symlink's referent. + EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false)); + EXPECT_FALSE(PathExists(symlink_target)); +} + +TEST_F(FileUtilTest, CopyDirectoryExclFileOverFifo) { + // Create a directory. + FilePath dir_name_from = + temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_From_Subdir")); + ASSERT_TRUE(CreateDirectory(dir_name_from)); + ASSERT_TRUE(PathExists(dir_name_from)); + + // Create a file under the directory. + FilePath file_name_from = + dir_name_from.Append(FILE_PATH_LITERAL("Copy_Test_File.txt")); + CreateTextFile(file_name_from, L"Gooooooooooooooooooooogle"); + ASSERT_TRUE(PathExists(file_name_from)); + + // Create a destination directory with a fifo of the same name. + FilePath dir_name_to = + temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Copy_To_Subdir")); + ASSERT_TRUE(CreateDirectory(dir_name_to)); + ASSERT_TRUE(PathExists(dir_name_to)); + + FilePath fifo_name_to = + dir_name_to.Append(FILE_PATH_LITERAL("Copy_Test_File.txt")); + ASSERT_EQ(0, mkfifo(fifo_name_to.value().c_str(), 0644)); + ASSERT_TRUE(PathExists(fifo_name_to)); + + // Check that copying fails. + EXPECT_FALSE(CopyDirectoryExcl(dir_name_from, dir_name_to, false)); +} #endif // !defined(OS_FUCHSIA) && defined(OS_POSIX) TEST_F(FileUtilTest, CopyFile) {
diff --git a/base/files/file_util_win.cc b/base/files/file_util_win.cc index d484ded..6b268cdb 100644 --- a/base/files/file_util_win.cc +++ b/base/files/file_util_win.cc
@@ -80,93 +80,43 @@ 1, mode_char); } -} // namespace - -FilePath MakeAbsoluteFilePath(const FilePath& input) { +bool DoCopyFile(const FilePath& from_path, + const FilePath& to_path, + bool fail_if_exists) { AssertBlockingAllowed(); - wchar_t file_path[MAX_PATH]; - if (!_wfullpath(file_path, input.value().c_str(), MAX_PATH)) - return FilePath(); - return FilePath(file_path); -} - -bool DeleteFile(const FilePath& path, bool recursive) { - AssertBlockingAllowed(); - - if (path.empty()) - return true; - - if (path.value().length() >= MAX_PATH) + if (from_path.ReferencesParent() || to_path.ReferencesParent()) return false; - // Handle any path with wildcards. - if (path.BaseName().value().find_first_of(L"*?") != - FilePath::StringType::npos) { - return DeleteFileRecursive(path.DirName(), path.BaseName().value(), - recursive); - } - DWORD attr = GetFileAttributes(path.value().c_str()); - // We're done if we can't find the path. - if (attr == INVALID_FILE_ATTRIBUTES) - return true; - // We may need to clear the read-only bit. - if ((attr & FILE_ATTRIBUTE_READONLY) && - !SetFileAttributes(path.value().c_str(), - attr & ~FILE_ATTRIBUTE_READONLY)) { + // NOTE: I suspect we could support longer paths, but that would involve + // analyzing all our usage of files. + if (from_path.value().length() >= MAX_PATH || + to_path.value().length() >= MAX_PATH) { return false; } - // Directories are handled differently if they're recursive. - if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) - return !!::DeleteFile(path.value().c_str()); - // Handle a simple, single file delete. - if (!recursive || DeleteFileRecursive(path, L"*", true)) - return !!RemoveDirectory(path.value().c_str()); - return false; -} - -bool DeleteFileAfterReboot(const FilePath& path) { - AssertBlockingAllowed(); - - if (path.value().length() >= MAX_PATH) + // Unlike the posix implementation that copies the file manually and discards + // the ACL bits, CopyFile() copies the complete SECURITY_DESCRIPTOR and access + // bits, which is usually not what we want. We can't do much about the + // SECURITY_DESCRIPTOR but at least remove the read only bit. + const wchar_t* dest = to_path.value().c_str(); + if (!::CopyFile(from_path.value().c_str(), dest, fail_if_exists)) { + // Copy failed. return false; - - return MoveFileEx(path.value().c_str(), NULL, - MOVEFILE_DELAY_UNTIL_REBOOT | - MOVEFILE_REPLACE_EXISTING) != FALSE; + } + DWORD attrs = GetFileAttributes(dest); + if (attrs == INVALID_FILE_ATTRIBUTES) { + return false; + } + if (attrs & FILE_ATTRIBUTE_READONLY) { + SetFileAttributes(dest, attrs & ~FILE_ATTRIBUTE_READONLY); + } + return true; } -bool ReplaceFile(const FilePath& from_path, - const FilePath& to_path, - File::Error* error) { - AssertBlockingAllowed(); - // Try a simple move first. It will only succeed when |to_path| doesn't - // already exist. - if (::MoveFile(from_path.value().c_str(), to_path.value().c_str())) - return true; - File::Error move_error = File::GetLastFileError(); - - // Try the full-blown replace if the move fails, as ReplaceFile will only - // succeed when |to_path| does exist. When writing to a network share, we may - // not be able to change the ACLs. Ignore ACL errors then - // (REPLACEFILE_IGNORE_MERGE_ERRORS). - if (::ReplaceFile(to_path.value().c_str(), from_path.value().c_str(), NULL, - REPLACEFILE_IGNORE_MERGE_ERRORS, NULL, NULL)) { - return true; - } - // In the case of FILE_ERROR_NOT_FOUND from ReplaceFile, it is likely that - // |to_path| does not exist. In this case, the more relevant error comes - // from the call to MoveFile. - if (error) { - File::Error replace_error = File::GetLastFileError(); - *error = replace_error == File::FILE_ERROR_NOT_FOUND ? move_error - : replace_error; - } - return false; -} - -bool CopyDirectory(const FilePath& from_path, const FilePath& to_path, - bool recursive) { +bool DoCopyDirectory(const FilePath& from_path, + const FilePath& to_path, + bool recursive, + bool fail_if_exists) { // NOTE(maruel): Previous version of this function used to call // SHFileOperation(). This used to copy the file attributes and extended // attributes, OLE structured storage, NTFS file system alternate data @@ -239,7 +189,7 @@ << target_path.value().c_str(); success = false; } - } else if (!CopyFile(current, target_path)) { + } else if (!DoCopyFile(current, target_path, fail_if_exists)) { DLOG(ERROR) << "CopyDirectory() couldn't create file: " << target_path.value().c_str(); success = false; @@ -253,6 +203,103 @@ return success; } +} // namespace + +FilePath MakeAbsoluteFilePath(const FilePath& input) { + AssertBlockingAllowed(); + wchar_t file_path[MAX_PATH]; + if (!_wfullpath(file_path, input.value().c_str(), MAX_PATH)) + return FilePath(); + return FilePath(file_path); +} + +bool DeleteFile(const FilePath& path, bool recursive) { + AssertBlockingAllowed(); + + if (path.empty()) + return true; + + if (path.value().length() >= MAX_PATH) + return false; + + // Handle any path with wildcards. + if (path.BaseName().value().find_first_of(L"*?") != + FilePath::StringType::npos) { + return DeleteFileRecursive(path.DirName(), path.BaseName().value(), + recursive); + } + DWORD attr = GetFileAttributes(path.value().c_str()); + // We're done if we can't find the path. + if (attr == INVALID_FILE_ATTRIBUTES) + return true; + // We may need to clear the read-only bit. + if ((attr & FILE_ATTRIBUTE_READONLY) && + !SetFileAttributes(path.value().c_str(), + attr & ~FILE_ATTRIBUTE_READONLY)) { + return false; + } + // Directories are handled differently if they're recursive. + if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) + return !!::DeleteFile(path.value().c_str()); + // Handle a simple, single file delete. + if (!recursive || DeleteFileRecursive(path, L"*", true)) + return !!RemoveDirectory(path.value().c_str()); + + return false; +} + +bool DeleteFileAfterReboot(const FilePath& path) { + AssertBlockingAllowed(); + + if (path.value().length() >= MAX_PATH) + return false; + + return MoveFileEx(path.value().c_str(), NULL, + MOVEFILE_DELAY_UNTIL_REBOOT | + MOVEFILE_REPLACE_EXISTING) != FALSE; +} + +bool ReplaceFile(const FilePath& from_path, + const FilePath& to_path, + File::Error* error) { + AssertBlockingAllowed(); + // Try a simple move first. It will only succeed when |to_path| doesn't + // already exist. + if (::MoveFile(from_path.value().c_str(), to_path.value().c_str())) + return true; + File::Error move_error = File::OSErrorToFileError(GetLastError()); + + // Try the full-blown replace if the move fails, as ReplaceFile will only + // succeed when |to_path| does exist. When writing to a network share, we may + // not be able to change the ACLs. Ignore ACL errors then + // (REPLACEFILE_IGNORE_MERGE_ERRORS). + if (::ReplaceFile(to_path.value().c_str(), from_path.value().c_str(), NULL, + REPLACEFILE_IGNORE_MERGE_ERRORS, NULL, NULL)) { + return true; + } + // In the case of FILE_ERROR_NOT_FOUND from ReplaceFile, it is likely that + // |to_path| does not exist. In this case, the more relevant error comes + // from the call to MoveFile. + if (error) { + File::Error replace_error = File::OSErrorToFileError(GetLastError()); + *error = replace_error == File::FILE_ERROR_NOT_FOUND ? move_error + : replace_error; + } + return false; +} + +bool CopyDirectory(const FilePath& from_path, + const FilePath& to_path, + bool recursive) { + return DoCopyDirectory(from_path, to_path, recursive, false); +} + +bool CopyDirectoryExcl(const FilePath& from_path, + const FilePath& to_path, + bool recursive) { + return DoCopyDirectory(from_path, to_path, recursive, true); +} + bool PathExists(const FilePath& path) { AssertBlockingAllowed(); return (GetFileAttributes(path.value().c_str()) != INVALID_FILE_ATTRIBUTES); @@ -774,34 +821,7 @@ } bool CopyFile(const FilePath& from_path, const FilePath& to_path) { - AssertBlockingAllowed(); - if (from_path.ReferencesParent() || to_path.ReferencesParent()) - return false; - - // NOTE: I suspect we could support longer paths, but that would involve - // analyzing all our usage of files. - if (from_path.value().length() >= MAX_PATH || - to_path.value().length() >= MAX_PATH) { - return false; - } - - // Unlike the posix implementation that copies the file manually and discards - // the ACL bits, CopyFile() copies the complete SECURITY_DESCRIPTOR and access - // bits, which is usually not what we want. We can't do much about the - // SECURITY_DESCRIPTOR but at least remove the read only bit. - const wchar_t* dest = to_path.value().c_str(); - if (!::CopyFile(from_path.value().c_str(), dest, false)) { - // Copy failed. - return false; - } - DWORD attrs = GetFileAttributes(dest); - if (attrs == INVALID_FILE_ATTRIBUTES) { - return false; - } - if (attrs & FILE_ATTRIBUTE_READONLY) { - SetFileAttributes(dest, attrs & ~FILE_ATTRIBUTE_READONLY); - } - return true; + return DoCopyFile(from_path, to_path, false); } bool SetNonBlocking(int fd) {
diff --git a/base/process/process_util_unittest.cc b/base/process/process_util_unittest.cc index 0f3f653..86cf3dfd 100644 --- a/base/process/process_util_unittest.cc +++ b/base/process/process_util_unittest.cc
@@ -771,8 +771,10 @@ // Read from the pipe to verify that the child received it. zx_signals_t signals = 0; - result = zx_object_wait_one(handles[1], ZX_SOCKET_READABLE, - zx_deadline_after(ZX_SEC(5)), &signals); + result = zx_object_wait_one( + handles[1], ZX_SOCKET_READABLE, + (base::TimeTicks::Now() + TestTimeouts::action_timeout()).ToZxTime(), + &signals); EXPECT_EQ(ZX_OK, result); EXPECT_TRUE(signals & ZX_SOCKET_READABLE); @@ -786,8 +788,8 @@ CHECK_EQ(ZX_OK, zx_handle_close(handles[1])); int exit_code; - ASSERT_TRUE( - process.WaitForExitWithTimeout(TimeDelta::FromSeconds(5), &exit_code)); + ASSERT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_timeout(), + &exit_code)); EXPECT_EQ(0, exit_code); } #endif // defined(OS_FUCHSIA)
diff --git a/base/task_scheduler/delayed_task_manager.cc b/base/task_scheduler/delayed_task_manager.cc index 5cf1895..e6f0e498 100644 --- a/base/task_scheduler/delayed_task_manager.cc +++ b/base/task_scheduler/delayed_task_manager.cc
@@ -41,23 +41,23 @@ const TimeTicks now = tick_clock_->NowTicks(); for (auto& task_and_callback : tasks_added_before_start) { const TimeDelta delay = - std::max(TimeDelta(), task_and_callback.first->delayed_run_time - now); + std::max(TimeDelta(), task_and_callback.first.delayed_run_time - now); AddDelayedTaskNow(std::move(task_and_callback.first), delay, std::move(task_and_callback.second)); } } void DelayedTaskManager::AddDelayedTask( - std::unique_ptr<Task> task, + Task task, PostTaskNowCallback post_task_now_callback) { - DCHECK(task); + DCHECK(task.task); - const TimeDelta delay = task->delay; + const TimeDelta delay = task.delay; DCHECK(!delay.is_zero()); // Use CHECK instead of DCHECK to crash earlier. See http://crbug.com/711167 // for details. - CHECK(task->task); + CHECK(task.task); // If |started_| is set, the DelayedTaskManager is in a stable state and // AddDelayedTaskNow() can be called without synchronization. Otherwise, it is @@ -78,10 +78,10 @@ } void DelayedTaskManager::AddDelayedTaskNow( - std::unique_ptr<Task> task, + Task task, TimeDelta delay, PostTaskNowCallback post_task_now_callback) { - DCHECK(task); + DCHECK(task.task); DCHECK(started_.IsSet()); // TODO(fdoray): Use |task->delayed_run_time| on the service thread // MessageLoop rather than recomputing it from |delay|.
diff --git a/base/task_scheduler/delayed_task_manager.h b/base/task_scheduler/delayed_task_manager.h index 86ab56a..2d6babb 100644 --- a/base/task_scheduler/delayed_task_manager.h +++ b/base/task_scheduler/delayed_task_manager.h
@@ -33,7 +33,7 @@ class BASE_EXPORT DelayedTaskManager { public: // Posts |task| for execution immediately. - using PostTaskNowCallback = OnceCallback<void(std::unique_ptr<Task> task)>; + using PostTaskNowCallback = OnceCallback<void(Task task)>; // |tick_clock| can be specified for testing. DelayedTaskManager(std::unique_ptr<TickClock> tick_clock = @@ -48,13 +48,12 @@ // Schedules a call to |post_task_now_callback| with |task| as argument when // |task| is ripe for execution and Start() has been called. - void AddDelayedTask(std::unique_ptr<Task> task, - PostTaskNowCallback post_task_now_callback); + void AddDelayedTask(Task task, PostTaskNowCallback post_task_now_callback); private: // Schedules a call to |post_task_now_callback| with |task| as argument when // |delay| expires. Start() must have been called before this. - void AddDelayedTaskNow(std::unique_ptr<Task> task, + void AddDelayedTaskNow(Task task, TimeDelta delay, PostTaskNowCallback post_task_now_callback); @@ -70,8 +69,7 @@ SchedulerLock lock_; scoped_refptr<TaskRunner> service_thread_task_runner_; - std::vector<std::pair<std::unique_ptr<Task>, PostTaskNowCallback>> - tasks_added_before_start_; + std::vector<std::pair<Task, PostTaskNowCallback>> tasks_added_before_start_; DISALLOW_COPY_AND_ASSIGN(DelayedTaskManager); };
diff --git a/base/task_scheduler/delayed_task_manager_unittest.cc b/base/task_scheduler/delayed_task_manager_unittest.cc index b3dbf07..8cfe04a2 100644 --- a/base/task_scheduler/delayed_task_manager_unittest.cc +++ b/base/task_scheduler/delayed_task_manager_unittest.cc
@@ -22,49 +22,36 @@ constexpr TimeDelta kLongDelay = TimeDelta::FromHours(1); -class MockTaskTarget { +class MockTask { public: - MockTaskTarget() = default; - ~MockTaskTarget() = default; - - // gMock currently doesn't support move-only types, so PostTaskNowCallback() - // handles the move-only type and forwards to the mocked method. - MOCK_METHOD1(DoPostTaskNowCallback, void(const Task*)); - - void PostTaskNowCallback(std::unique_ptr<Task> task) { - DoPostTaskNowCallback(task.get()); - } - - private: - DISALLOW_COPY_AND_ASSIGN(MockTaskTarget); + MOCK_METHOD0(Run, void()); }; +void RunTask(Task task) { + std::move(task.task).Run(); +} + class TaskSchedulerDelayedTaskManagerTest : public testing::Test { - public: + protected: TaskSchedulerDelayedTaskManagerTest() - : delayed_task_manager_(service_thread_task_runner_->GetMockTickClock()) { + : delayed_task_manager_(service_thread_task_runner_->GetMockTickClock()), + task_(FROM_HERE, + BindOnce(&MockTask::Run, Unretained(&mock_task_)), + TaskTraits(), + kLongDelay) { + // The constructor of Task computes |delayed_run_time| by adding |delay| to + // the real time. Recompute it by adding |delay| to the mock time. + task_.delayed_run_time = + service_thread_task_runner_->GetMockTickClock()->NowTicks() + + kLongDelay; } ~TaskSchedulerDelayedTaskManagerTest() override = default; - protected: - std::unique_ptr<Task> CreateTask(TimeDelta delay) { - auto task = std::make_unique<Task>(FROM_HERE, BindOnce(&DoNothing), - TaskTraits(), delay); - - // The constructor of Task computes |delayed_run_time| by adding |delay| to - // the real time. Recompute it by adding |delay| to the mock time. - task->delayed_run_time = - service_thread_task_runner_->GetMockTickClock()->NowTicks() + delay; - - return task; - } - - testing::StrictMock<MockTaskTarget> task_target_; const scoped_refptr<TestMockTimeTaskRunner> service_thread_task_runner_ = MakeRefCounted<TestMockTimeTaskRunner>(); DelayedTaskManager delayed_task_manager_; - std::unique_ptr<Task> task_ = CreateTask(kLongDelay); - Task* const task_raw_ = task_.get(); + testing::StrictMock<MockTask> mock_task_; + Task task_; private: DISALLOW_COPY_AND_ASSIGN(TaskSchedulerDelayedTaskManagerTest); @@ -75,14 +62,11 @@ // Verify that a delayed task isn't forwarded before Start(). TEST_F(TaskSchedulerDelayedTaskManagerTest, DelayedTaskDoesNotRunBeforeStart) { // Send |task| to the DelayedTaskManager. - delayed_task_manager_.AddDelayedTask( - std::move(task_), BindOnce(&MockTaskTarget::PostTaskNowCallback, - Unretained(&task_target_))); + delayed_task_manager_.AddDelayedTask(std::move(task_), BindOnce(&RunTask)); // Fast-forward time until the task is ripe for execution. Since Start() has - // not been called, the task should be forwarded to |task_target_| - // (|task_target_| is a StrictMock without expectations, so the test will fail - // if the task is forwarded to it). + // not been called, the task should not be forwarded to RunTask() (MockTask is + // a StrictMock without expectations so test will fail if RunTask() runs it). service_thread_task_runner_->FastForwardBy(kLongDelay); } @@ -91,9 +75,7 @@ TEST_F(TaskSchedulerDelayedTaskManagerTest, DelayedTaskPostedBeforeStartExpiresAfterStartRunsOnExpire) { // Send |task| to the DelayedTaskManager. - delayed_task_manager_.AddDelayedTask( - std::move(task_), BindOnce(&MockTaskTarget::PostTaskNowCallback, - Unretained(&task_target_))); + delayed_task_manager_.AddDelayedTask(std::move(task_), BindOnce(&RunTask)); delayed_task_manager_.Start(service_thread_task_runner_); @@ -102,8 +84,8 @@ service_thread_task_runner_->RunUntilIdle(); // Fast-forward time until the task is ripe for execution. Expect the task to - // be forwarded to |task_target_|. - EXPECT_CALL(task_target_, DoPostTaskNowCallback(task_raw_)); + // be forwarded to RunTask(). + EXPECT_CALL(mock_task_, Run()); service_thread_task_runner_->FastForwardBy(kLongDelay); } @@ -112,9 +94,7 @@ TEST_F(TaskSchedulerDelayedTaskManagerTest, DelayedTaskPostedBeforeStartExpiresBeforeStartRunsOnStart) { // Send |task| to the DelayedTaskManager. - delayed_task_manager_.AddDelayedTask( - std::move(task_), BindOnce(&MockTaskTarget::PostTaskNowCallback, - Unretained(&task_target_))); + delayed_task_manager_.AddDelayedTask(std::move(task_), BindOnce(&RunTask)); // Run tasks on the service thread. Don't expect any forwarding to // |task_target_| since the task isn't ripe for execution. @@ -124,9 +104,8 @@ // task to be forwarded since Start() hasn't been called yet. service_thread_task_runner_->FastForwardBy(kLongDelay); - // Start the DelayedTaskManager. Expect the task to be forwarded to - // |task_target_|. - EXPECT_CALL(task_target_, DoPostTaskNowCallback(task_raw_)); + // Start the DelayedTaskManager. Expect the task to be forwarded to RunTask(). + EXPECT_CALL(mock_task_, Run()); delayed_task_manager_.Start(service_thread_task_runner_); service_thread_task_runner_->RunUntilIdle(); } @@ -137,12 +116,10 @@ delayed_task_manager_.Start(service_thread_task_runner_); // Send |task| to the DelayedTaskManager. - delayed_task_manager_.AddDelayedTask( - std::move(task_), BindOnce(&MockTaskTarget::PostTaskNowCallback, - Unretained(&task_target_))); + delayed_task_manager_.AddDelayedTask(std::move(task_), BindOnce(&RunTask)); // Run tasks that are ripe for execution. Don't expect any forwarding to - // |task_target_|. + // RunTask(). service_thread_task_runner_->RunUntilIdle(); } @@ -152,12 +129,10 @@ delayed_task_manager_.Start(service_thread_task_runner_); // Send |task| to the DelayedTaskManager. - delayed_task_manager_.AddDelayedTask( - std::move(task_), BindOnce(&MockTaskTarget::PostTaskNowCallback, - Unretained(&task_target_))); + delayed_task_manager_.AddDelayedTask(std::move(task_), BindOnce(&RunTask)); - // Fast-forward time. Expect the task is forwarded to |task_target_|. - EXPECT_CALL(task_target_, DoPostTaskNowCallback(task_raw_)); + // Fast-forward time. Expect the task to be forwarded to RunTask(). + EXPECT_CALL(mock_task_, Run()); service_thread_task_runner_->FastForwardBy(kLongDelay); } @@ -165,44 +140,40 @@ // they are ripe for execution. TEST_F(TaskSchedulerDelayedTaskManagerTest, DelayedTasksRunAfterDelay) { delayed_task_manager_.Start(service_thread_task_runner_); - auto task_a = std::make_unique<Task>(FROM_HERE, BindOnce(&DoNothing), - TaskTraits(), TimeDelta::FromHours(1)); - const Task* task_a_raw = task_a.get(); - auto task_b = std::make_unique<Task>(FROM_HERE, BindOnce(&DoNothing), - TaskTraits(), TimeDelta::FromHours(2)); - const Task* task_b_raw = task_b.get(); + testing::StrictMock<MockTask> mock_task_a; + Task task_a(FROM_HERE, BindOnce(&MockTask::Run, Unretained(&mock_task_a)), + TaskTraits(), TimeDelta::FromHours(1)); - auto task_c = std::make_unique<Task>(FROM_HERE, BindOnce(&DoNothing), - TaskTraits(), TimeDelta::FromHours(1)); - const Task* task_c_raw = task_c.get(); + testing::StrictMock<MockTask> mock_task_b; + Task task_b(FROM_HERE, BindOnce(&MockTask::Run, Unretained(&mock_task_b)), + TaskTraits(), TimeDelta::FromHours(2)); + + testing::StrictMock<MockTask> mock_task_c; + Task task_c(FROM_HERE, BindOnce(&MockTask::Run, Unretained(&mock_task_c)), + TaskTraits(), TimeDelta::FromHours(1)); // Send tasks to the DelayedTaskManager. - delayed_task_manager_.AddDelayedTask( - std::move(task_a), BindOnce(&MockTaskTarget::PostTaskNowCallback, - Unretained(&task_target_))); - delayed_task_manager_.AddDelayedTask( - std::move(task_b), BindOnce(&MockTaskTarget::PostTaskNowCallback, - Unretained(&task_target_))); - delayed_task_manager_.AddDelayedTask( - std::move(task_c), BindOnce(&MockTaskTarget::PostTaskNowCallback, - Unretained(&task_target_))); + delayed_task_manager_.AddDelayedTask(std::move(task_a), BindOnce(&RunTask)); + delayed_task_manager_.AddDelayedTask(std::move(task_b), BindOnce(&RunTask)); + delayed_task_manager_.AddDelayedTask(std::move(task_c), BindOnce(&RunTask)); // Run tasks that are ripe for execution on the service thread. Don't expect - // any call to |task_target_|. + // any call to RunTask(). service_thread_task_runner_->RunUntilIdle(); - // Fast-forward time. Expect |task_a_raw| and |task_c_raw| to be forwarded to + // Fast-forward time. Expect |task_a| and |task_c| to be forwarded to // |task_target_|. - EXPECT_CALL(task_target_, DoPostTaskNowCallback(task_a_raw)); - EXPECT_CALL(task_target_, DoPostTaskNowCallback(task_c_raw)); + EXPECT_CALL(mock_task_a, Run()); + EXPECT_CALL(mock_task_c, Run()); service_thread_task_runner_->FastForwardBy(TimeDelta::FromHours(1)); - testing::Mock::VerifyAndClear(&task_target_); + testing::Mock::VerifyAndClear(&mock_task_a); + testing::Mock::VerifyAndClear(&mock_task_c); - // Fast-forward time. Expect |task_b_raw| to be forwarded to |task_target_|. - EXPECT_CALL(task_target_, DoPostTaskNowCallback(task_b_raw)); + // Fast-forward time. Expect |task_b| to be forwarded to RunTask(). + EXPECT_CALL(mock_task_b, Run()); service_thread_task_runner_->FastForwardBy(TimeDelta::FromHours(1)); - testing::Mock::VerifyAndClear(&task_target_); + testing::Mock::VerifyAndClear(&mock_task_b); } } // namespace internal
diff --git a/base/task_scheduler/priority_queue_unittest.cc b/base/task_scheduler/priority_queue_unittest.cc index 3d89d623..13756c8 100644 --- a/base/task_scheduler/priority_queue_unittest.cc +++ b/base/task_scheduler/priority_queue_unittest.cc
@@ -60,27 +60,26 @@ TEST(TaskSchedulerPriorityQueueTest, PushPopPeek) { // Create test sequences. scoped_refptr<Sequence> sequence_a(new Sequence); - sequence_a->PushTask(std::make_unique<Task>( - FROM_HERE, Bind(&DoNothing), TaskTraits(TaskPriority::USER_VISIBLE), - TimeDelta())); + sequence_a->PushTask(Task(FROM_HERE, Bind(&DoNothing), + TaskTraits(TaskPriority::USER_VISIBLE), + TimeDelta())); SequenceSortKey sort_key_a = sequence_a->GetSortKey(); scoped_refptr<Sequence> sequence_b(new Sequence); - sequence_b->PushTask(std::make_unique<Task>( - FROM_HERE, Bind(&DoNothing), TaskTraits(TaskPriority::USER_BLOCKING), - TimeDelta())); + sequence_b->PushTask(Task(FROM_HERE, Bind(&DoNothing), + TaskTraits(TaskPriority::USER_BLOCKING), + TimeDelta())); SequenceSortKey sort_key_b = sequence_b->GetSortKey(); scoped_refptr<Sequence> sequence_c(new Sequence); - sequence_c->PushTask(std::make_unique<Task>( - FROM_HERE, Bind(&DoNothing), TaskTraits(TaskPriority::USER_BLOCKING), - TimeDelta())); + sequence_c->PushTask(Task(FROM_HERE, Bind(&DoNothing), + TaskTraits(TaskPriority::USER_BLOCKING), + TimeDelta())); SequenceSortKey sort_key_c = sequence_c->GetSortKey(); scoped_refptr<Sequence> sequence_d(new Sequence); - sequence_d->PushTask(std::make_unique<Task>( - FROM_HERE, Bind(&DoNothing), TaskTraits(TaskPriority::BACKGROUND), - TimeDelta())); + sequence_d->PushTask(Task(FROM_HERE, Bind(&DoNothing), + TaskTraits(TaskPriority::BACKGROUND), TimeDelta())); SequenceSortKey sort_key_d = sequence_d->GetSortKey(); // Create a PriorityQueue and a Transaction.
diff --git a/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc b/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc index 0ebe559..285aa1e 100644 --- a/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc +++ b/base/task_scheduler/scheduler_single_thread_task_runner_manager.cc
@@ -237,16 +237,15 @@ scoped_refptr<Sequence> GetWorkFromWindowsMessageQueue() { MSG msg; if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE) != FALSE) { - auto pump_message_task = - std::make_unique<Task>(FROM_HERE, - Bind( - [](MSG msg) { - TranslateMessage(&msg); - DispatchMessage(&msg); - }, - std::move(msg)), - TaskTraits(MayBlock()), TimeDelta()); - if (task_tracker_->WillPostTask(pump_message_task.get())) { + Task pump_message_task(FROM_HERE, + Bind( + [](MSG msg) { + TranslateMessage(&msg); + DispatchMessage(&msg); + }, + std::move(msg)), + TaskTraits(MayBlock()), TimeDelta()); + if (task_tracker_->WillPostTask(pump_message_task)) { bool was_empty = message_pump_sequence_->PushTask(std::move(pump_message_task)); DCHECK(was_empty) << "GetWorkFromWindowsMessageQueue() does not expect " @@ -294,14 +293,13 @@ if (!g_manager_is_alive) return false; - auto task = - std::make_unique<Task>(from_here, std::move(closure), traits_, delay); - task->single_thread_task_runner_ref = this; + Task task(from_here, std::move(closure), traits_, delay); + task.single_thread_task_runner_ref = this; - if (!outer_->task_tracker_->WillPostTask(task.get())) + if (!outer_->task_tracker_->WillPostTask(task)) return false; - if (task->delayed_run_time.is_null()) { + if (task.delayed_run_time.is_null()) { PostTaskNow(std::move(task)); } else { outer_->delayed_task_manager_->AddDelayedTask( @@ -351,7 +349,7 @@ } } - void PostTaskNow(std::unique_ptr<Task> task) { + void PostTaskNow(Task task) { scoped_refptr<Sequence> sequence = GetDelegate()->sequence(); // If |sequence| is null, then the thread is effectively gone (either // shutdown or joined).
diff --git a/base/task_scheduler/scheduler_worker_pool.cc b/base/task_scheduler/scheduler_worker_pool.cc index 1063b40b..ee3c232 100644 --- a/base/task_scheduler/scheduler_worker_pool.cc +++ b/base/task_scheduler/scheduler_worker_pool.cc
@@ -62,7 +62,7 @@ // Post the task as part of a one-off single-task Sequence. return worker_pool_->PostTaskWithSequence( - std::make_unique<Task>(from_here, std::move(closure), traits_, delay), + Task(from_here, std::move(closure), traits_, delay), MakeRefCounted<Sequence>()); } @@ -98,9 +98,8 @@ if (!g_active_pools_count) return false; - std::unique_ptr<Task> task = - std::make_unique<Task>(from_here, std::move(closure), traits_, delay); - task->sequenced_task_runner_ref = this; + Task task(from_here, std::move(closure), traits_, delay); + task.sequenced_task_runner_ref = this; // Post the task as part of |sequence_|. return worker_pool_->PostTaskWithSequence(std::move(task), sequence_); @@ -141,29 +140,28 @@ } bool SchedulerWorkerPool::PostTaskWithSequence( - std::unique_ptr<Task> task, + Task task, scoped_refptr<Sequence> sequence) { - DCHECK(task); + DCHECK(task.task); DCHECK(sequence); - if (!task_tracker_->WillPostTask(task.get())) + if (!task_tracker_->WillPostTask(task)) return false; - if (task->delayed_run_time.is_null()) { + if (task.delayed_run_time.is_null()) { PostTaskWithSequenceNow(std::move(task), std::move(sequence)); } else { // Use CHECK instead of DCHECK to crash earlier. See http://crbug.com/711167 // for details. - CHECK(task->task); + CHECK(task.task); delayed_task_manager_->AddDelayedTask( - std::move(task), - BindOnce( - [](scoped_refptr<Sequence> sequence, - SchedulerWorkerPool* worker_pool, std::unique_ptr<Task> task) { - worker_pool->PostTaskWithSequenceNow(std::move(task), - std::move(sequence)); - }, - std::move(sequence), Unretained(this))); + std::move(task), BindOnce( + [](scoped_refptr<Sequence> sequence, + SchedulerWorkerPool* worker_pool, Task task) { + worker_pool->PostTaskWithSequenceNow( + std::move(task), std::move(sequence)); + }, + std::move(sequence), Unretained(this))); } return true; @@ -194,14 +192,14 @@ } void SchedulerWorkerPool::PostTaskWithSequenceNow( - std::unique_ptr<Task> task, + Task task, scoped_refptr<Sequence> sequence) { - DCHECK(task); + DCHECK(task.task); DCHECK(sequence); // Confirm that |task| is ready to run (its delayed run time is either null or // in the past). - DCHECK_LE(task->delayed_run_time, TimeTicks::Now()); + DCHECK_LE(task.delayed_run_time, TimeTicks::Now()); const bool sequence_was_empty = sequence->PushTask(std::move(task)); if (sequence_was_empty) {
diff --git a/base/task_scheduler/scheduler_worker_pool.h b/base/task_scheduler/scheduler_worker_pool.h index 9aa237d..1b80d04 100644 --- a/base/task_scheduler/scheduler_worker_pool.h +++ b/base/task_scheduler/scheduler_worker_pool.h
@@ -5,8 +5,6 @@ #ifndef BASE_TASK_SCHEDULER_SCHEDULER_WORKER_POOL_H_ #define BASE_TASK_SCHEDULER_SCHEDULER_WORKER_POOL_H_ -#include <memory> - #include "base/base_export.h" #include "base/memory/ref_counted.h" #include "base/sequenced_task_runner.h" @@ -42,8 +40,7 @@ // Posts |task| to be executed by this SchedulerWorkerPool as part of // |sequence|. |task| won't be executed before its delayed run time, if any. // Returns true if |task| is posted. - bool PostTaskWithSequence(std::unique_ptr<Task> task, - scoped_refptr<Sequence> sequence); + bool PostTaskWithSequence(Task task, scoped_refptr<Sequence> sequence); // Registers the worker pool in TLS. void BindToCurrentThread(); @@ -66,8 +63,7 @@ // Posts |task| to be executed by this SchedulerWorkerPool as part of // |sequence|. This must only be called after |task| has gone through // PostTaskWithSequence() and after |task|'s delayed run time. - void PostTaskWithSequenceNow(std::unique_ptr<Task> task, - scoped_refptr<Sequence> sequence); + void PostTaskWithSequenceNow(Task task, scoped_refptr<Sequence> sequence); TaskTracker* const task_tracker_; DelayedTaskManager* const delayed_task_manager_;
diff --git a/base/task_scheduler/scheduler_worker_unittest.cc b/base/task_scheduler/scheduler_worker_unittest.cc index 21b482dc..5400cbb 100644 --- a/base/task_scheduler/scheduler_worker_unittest.cc +++ b/base/task_scheduler/scheduler_worker_unittest.cc
@@ -176,12 +176,11 @@ // Create a Sequence with TasksPerSequence() Tasks. scoped_refptr<Sequence> sequence(new Sequence); for (size_t i = 0; i < outer_->TasksPerSequence(); ++i) { - std::unique_ptr<Task> task( - new Task(FROM_HERE, - BindOnce(&TaskSchedulerWorkerTest::RunTaskCallback, - Unretained(outer_)), - TaskTraits(), TimeDelta())); - EXPECT_TRUE(outer_->task_tracker_.WillPostTask(task.get())); + Task task(FROM_HERE, + BindOnce(&TaskSchedulerWorkerTest::RunTaskCallback, + Unretained(outer_)), + TaskTraits(), TimeDelta()); + EXPECT_TRUE(outer_->task_tracker_.WillPostTask(task)); sequence->PushTask(std::move(task)); } @@ -446,7 +445,7 @@ controls_->work_requested_ = true; scoped_refptr<Sequence> sequence(new Sequence); - std::unique_ptr<Task> task(new Task( + Task task( FROM_HERE, BindOnce( [](WaitableEvent* work_processed, WaitableEvent* work_running) { @@ -456,8 +455,8 @@ Unretained(&controls_->work_processed_), Unretained(&controls_->work_running_)), {WithBaseSyncPrimitives(), TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, - TimeDelta())); - EXPECT_TRUE(task_tracker_->WillPostTask(task.get())); + TimeDelta()); + EXPECT_TRUE(task_tracker_->WillPostTask(task)); sequence->PushTask(std::move(task)); sequence = task_tracker_->WillScheduleSequence(std::move(sequence), nullptr);
diff --git a/base/task_scheduler/sequence.cc b/base/task_scheduler/sequence.cc index 4db5478..4737f8e 100644 --- a/base/task_scheduler/sequence.cc +++ b/base/task_scheduler/sequence.cc
@@ -14,30 +14,27 @@ Sequence::Sequence() = default; -bool Sequence::PushTask(std::unique_ptr<Task> task) { - DCHECK(task); - +bool Sequence::PushTask(Task task) { // Use CHECK instead of DCHECK to crash earlier. See http://crbug.com/711167 // for details. - CHECK(task->task); - DCHECK(task->sequenced_time.is_null()); - task->sequenced_time = base::TimeTicks::Now(); + CHECK(task.task); + DCHECK(task.sequenced_time.is_null()); + task.sequenced_time = base::TimeTicks::Now(); AutoSchedulerLock auto_lock(lock_); - ++num_tasks_per_priority_[static_cast<int>(task->traits.priority())]; + ++num_tasks_per_priority_[static_cast<int>(task.traits.priority())]; queue_.push(std::move(task)); // Return true if the sequence was empty before the push. return queue_.size() == 1; } -std::unique_ptr<Task> Sequence::TakeTask() { +Optional<Task> Sequence::TakeTask() { AutoSchedulerLock auto_lock(lock_); DCHECK(!queue_.empty()); - DCHECK(queue_.front()); + DCHECK(queue_.front().task); - const int priority_index = - static_cast<int>(queue_.front()->traits.priority()); + const int priority_index = static_cast<int>(queue_.front().traits.priority()); DCHECK_GT(num_tasks_per_priority_[priority_index], 0U); --num_tasks_per_priority_[priority_index]; @@ -47,14 +44,14 @@ TaskTraits Sequence::PeekTaskTraits() const { AutoSchedulerLock auto_lock(lock_); DCHECK(!queue_.empty()); - DCHECK(queue_.front()); - return queue_.front()->traits; + DCHECK(queue_.front().task); + return queue_.front().traits; } bool Sequence::Pop() { AutoSchedulerLock auto_lock(lock_); DCHECK(!queue_.empty()); - DCHECK(!queue_.front()); + DCHECK(!queue_.front().task); queue_.pop(); return queue_.empty(); } @@ -78,7 +75,7 @@ } // Save the sequenced time of the next task in the sequence. - next_task_sequenced_time = queue_.front()->sequenced_time; + next_task_sequenced_time = queue_.front().sequenced_time; } return SequenceSortKey(priority, next_task_sequenced_time);
diff --git a/base/task_scheduler/sequence.h b/base/task_scheduler/sequence.h index feec70a..ec5e8c1 100644 --- a/base/task_scheduler/sequence.h +++ b/base/task_scheduler/sequence.h
@@ -7,12 +7,11 @@ #include <stddef.h> -#include <memory> - #include "base/base_export.h" #include "base/containers/queue.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/optional.h" #include "base/sequence_token.h" #include "base/task_scheduler/scheduler_lock.h" #include "base/task_scheduler/sequence_sort_key.h" @@ -47,13 +46,18 @@ // Adds |task| in a new slot at the end of the Sequence. Returns true if the // Sequence was empty before this operation. - bool PushTask(std::unique_ptr<Task> task); + bool PushTask(Task task); // Transfers ownership of the Task in the front slot of the Sequence to the // caller. The front slot of the Sequence will be nullptr and remain until // Pop(). Cannot be called on an empty Sequence or a Sequence whose front slot // is already nullptr. - std::unique_ptr<Task> TakeTask(); + // + // Because this method cannot be called on an empty Sequence, the returned + // Optional<Task> is never nullptr. An Optional is used in preparation for the + // merge between TaskScheduler and TaskQueueManager (in Blink). + // https://crbug.com/783309 + Optional<Task> TakeTask(); // Returns the TaskTraits of the Task in front of the Sequence. Cannot be // called on an empty Sequence or on a Sequence whose front slot is empty. @@ -85,7 +89,7 @@ mutable SchedulerLock lock_; // Queue of tasks to execute. - base::queue<std::unique_ptr<Task>> queue_; + base::queue<Task> queue_; // Number of tasks contained in the Sequence for each priority. size_t num_tasks_per_priority_[static_cast<int>(TaskPriority::HIGHEST) + 1] =
diff --git a/base/task_scheduler/sequence_unittest.cc b/base/task_scheduler/sequence_unittest.cc index bd4959a..aa634a0 100644 --- a/base/task_scheduler/sequence_unittest.cc +++ b/base/task_scheduler/sequence_unittest.cc
@@ -8,10 +8,10 @@ #include "base/bind.h" #include "base/bind_helpers.h" -#include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/test/gtest_util.h" #include "base/time/time.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { @@ -19,201 +19,154 @@ namespace { -class TaskSchedulerSequenceTest : public testing::Test { +class MockTask { public: - TaskSchedulerSequenceTest() - : task_a_owned_(new Task(FROM_HERE, - BindOnce(&DoNothing), - {TaskPriority::BACKGROUND}, - TimeDelta())), - task_b_owned_(new Task(FROM_HERE, - BindOnce(&DoNothing), - {TaskPriority::USER_VISIBLE}, - TimeDelta())), - task_c_owned_(new Task(FROM_HERE, - BindOnce(&DoNothing), - {TaskPriority::USER_BLOCKING}, - TimeDelta())), - task_d_owned_(new Task(FROM_HERE, - BindOnce(&DoNothing), - {TaskPriority::USER_BLOCKING}, - TimeDelta())), - task_e_owned_(new Task(FROM_HERE, - BindOnce(&DoNothing), - {TaskPriority::BACKGROUND}, - TimeDelta())), - task_a_(task_a_owned_.get()), - task_b_(task_b_owned_.get()), - task_c_(task_c_owned_.get()), - task_d_(task_d_owned_.get()), - task_e_(task_e_owned_.get()) {} - - protected: - // Tasks to be handed off to a Sequence for testing. - std::unique_ptr<Task> task_a_owned_; - std::unique_ptr<Task> task_b_owned_; - std::unique_ptr<Task> task_c_owned_; - std::unique_ptr<Task> task_d_owned_; - std::unique_ptr<Task> task_e_owned_; - - // Raw pointers to those same tasks for verification. This is needed because - // the unique_ptrs above no longer point to the tasks once they have been - // moved into a Sequence. - const Task* task_a_; - const Task* task_b_; - const Task* task_c_; - const Task* task_d_; - const Task* task_e_; - - private: - DISALLOW_COPY_AND_ASSIGN(TaskSchedulerSequenceTest); + MOCK_METHOD0(Run, void()); }; +Task CreateTask(MockTask* mock_task) { + return Task(FROM_HERE, BindOnce(&MockTask::Run, Unretained(mock_task)), + {TaskPriority::BACKGROUND}, TimeDelta()); +} + +void ExpectMockTask(MockTask* mock_task, Task* task) { + EXPECT_CALL(*mock_task, Run()); + std::move(task->task).Run(); + testing::Mock::VerifyAndClear(mock_task); +} + } // namespace -TEST_F(TaskSchedulerSequenceTest, PushTakeRemove) { - scoped_refptr<Sequence> sequence(new Sequence); +TEST(TaskSchedulerSequenceTest, PushTakeRemove) { + testing::StrictMock<MockTask> mock_task_a; + testing::StrictMock<MockTask> mock_task_b; + testing::StrictMock<MockTask> mock_task_c; + testing::StrictMock<MockTask> mock_task_d; + testing::StrictMock<MockTask> mock_task_e; - // Push task A in the sequence. Its sequenced time should be updated and it - // should be in front of the sequence. - EXPECT_TRUE(sequence->PushTask(std::move(task_a_owned_))); - EXPECT_FALSE(task_a_->sequenced_time.is_null()); - EXPECT_EQ(task_a_->traits.priority(), sequence->PeekTaskTraits().priority()); + scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>(); - // Push task B, C and D in the sequence. Their sequenced time should be - // updated and task A should always remain in front of the sequence. - EXPECT_FALSE(sequence->PushTask(std::move(task_b_owned_))); - EXPECT_FALSE(task_b_->sequenced_time.is_null()); - EXPECT_EQ(task_a_->traits.priority(), sequence->PeekTaskTraits().priority()); + // Push task A in the sequence. PushTask() should return true since it's the + // first task-> + EXPECT_TRUE(sequence->PushTask(CreateTask(&mock_task_a))); - EXPECT_FALSE(sequence->PushTask(std::move(task_c_owned_))); - EXPECT_FALSE(task_c_->sequenced_time.is_null()); - EXPECT_EQ(task_a_->traits.priority(), sequence->PeekTaskTraits().priority()); + // Push task B, C and D in the sequence. PushTask() should return false since + // there is already a task in a sequence. + EXPECT_FALSE(sequence->PushTask(CreateTask(&mock_task_b))); + EXPECT_FALSE(sequence->PushTask(CreateTask(&mock_task_c))); + EXPECT_FALSE(sequence->PushTask(CreateTask(&mock_task_d))); - EXPECT_FALSE(sequence->PushTask(std::move(task_d_owned_))); - EXPECT_FALSE(task_d_->sequenced_time.is_null()); - EXPECT_EQ(task_a_->traits.priority(), sequence->PeekTaskTraits().priority()); - - // Get the task in front of the sequence. It should be task A. - EXPECT_EQ(task_a_, sequence->TakeTask().get()); + // Take the task in front of the sequence. It should be task A. + Optional<Task> task = sequence->TakeTask(); + ExpectMockTask(&mock_task_a, &task.value()); + EXPECT_FALSE(task->sequenced_time.is_null()); // Remove the empty slot. Task B should now be in front. EXPECT_FALSE(sequence->Pop()); - EXPECT_EQ(task_b_, sequence->TakeTask().get()); + task = sequence->TakeTask(); + ExpectMockTask(&mock_task_b, &task.value()); + EXPECT_FALSE(task->sequenced_time.is_null()); // Remove the empty slot. Task C should now be in front. EXPECT_FALSE(sequence->Pop()); - EXPECT_EQ(task_c_, sequence->TakeTask().get()); + task = sequence->TakeTask(); + ExpectMockTask(&mock_task_c, &task.value()); + EXPECT_FALSE(task->sequenced_time.is_null()); - // Remove the empty slot. Task D should now be in front. + // Remove the empty slot. EXPECT_FALSE(sequence->Pop()); - EXPECT_EQ(task_d_, sequence->TakeTask().get()); - // Push task E in the sequence. Its sequenced time should be updated. - EXPECT_FALSE(sequence->PushTask(std::move(task_e_owned_))); - EXPECT_FALSE(task_e_->sequenced_time.is_null()); + // Push task E in the sequence. + EXPECT_FALSE(sequence->PushTask(CreateTask(&mock_task_e))); + + // Task D should be in front. + task = sequence->TakeTask(); + ExpectMockTask(&mock_task_d, &task.value()); + EXPECT_FALSE(task->sequenced_time.is_null()); // Remove the empty slot. Task E should now be in front. EXPECT_FALSE(sequence->Pop()); - EXPECT_EQ(task_e_, sequence->TakeTask().get()); + task = sequence->TakeTask(); + ExpectMockTask(&mock_task_e, &task.value()); + EXPECT_FALSE(task->sequenced_time.is_null()); // Remove the empty slot. The sequence should now be empty. EXPECT_TRUE(sequence->Pop()); } -TEST_F(TaskSchedulerSequenceTest, GetSortKey) { - scoped_refptr<Sequence> sequence(new Sequence); +// Verifies the sort key of a sequence that contains one BACKGROUND task. +TEST(TaskSchedulerSequenceTest, GetSortKeyBackground) { + // Create a sequence with a BACKGROUND task. + Task background_task(FROM_HERE, BindOnce(&DoNothing), + {TaskPriority::BACKGROUND}, TimeDelta()); + scoped_refptr<Sequence> background_sequence = MakeRefCounted<Sequence>(); + background_sequence->PushTask(std::move(background_task)); - // Push task A in the sequence. The highest priority is from task A - // (BACKGROUND). Task A is in front of the sequence. - sequence->PushTask(std::move(task_a_owned_)); - EXPECT_EQ(SequenceSortKey(TaskPriority::BACKGROUND, task_a_->sequenced_time), - sequence->GetSortKey()); + // Get the sort key. + const SequenceSortKey background_sort_key = background_sequence->GetSortKey(); - // Push task B in the sequence. The highest priority is from task B - // (USER_VISIBLE). Task A is still in front of the sequence. - sequence->PushTask(std::move(task_b_owned_)); - EXPECT_EQ( - SequenceSortKey(TaskPriority::USER_VISIBLE, task_a_->sequenced_time), - sequence->GetSortKey()); + // Take the task from the sequence, so that its sequenced time is available + // for the check below. + auto take_background_task = background_sequence->TakeTask(); - // Push task C in the sequence. The highest priority is from task C - // (USER_BLOCKING). Task A is still in front of the sequence. - sequence->PushTask(std::move(task_c_owned_)); - EXPECT_EQ( - SequenceSortKey(TaskPriority::USER_BLOCKING, task_a_->sequenced_time), - sequence->GetSortKey()); + // Verify the sort key. + EXPECT_EQ(TaskPriority::BACKGROUND, background_sort_key.priority()); + EXPECT_EQ(take_background_task->sequenced_time, + background_sort_key.next_task_sequenced_time()); - // Push task D in the sequence. The highest priority is from tasks C/D - // (USER_BLOCKING). Task A is still in front of the sequence. - sequence->PushTask(std::move(task_d_owned_)); - EXPECT_EQ( - SequenceSortKey(TaskPriority::USER_BLOCKING, task_a_->sequenced_time), - sequence->GetSortKey()); + // Pop for correctness. + background_sequence->Pop(); +} - // Pop task A. The highest priority is still USER_BLOCKING. The task in front - // of the sequence is now task B. - sequence->TakeTask(); - sequence->Pop(); - EXPECT_EQ( - SequenceSortKey(TaskPriority::USER_BLOCKING, task_b_->sequenced_time), - sequence->GetSortKey()); +// Same as TaskSchedulerSequenceTest.GetSortKeyBackground, but with a +// USER_VISIBLE task. +TEST(TaskSchedulerSequenceTest, GetSortKeyForeground) { + // Create a sequence with a USER_VISIBLE task. + Task foreground_task(FROM_HERE, BindOnce(&DoNothing), + {TaskPriority::USER_VISIBLE}, TimeDelta()); + scoped_refptr<Sequence> foreground_sequence = MakeRefCounted<Sequence>(); + foreground_sequence->PushTask(std::move(foreground_task)); - // Pop task B. The highest priority is still USER_BLOCKING. The task in front - // of the sequence is now task C. - sequence->TakeTask(); - sequence->Pop(); - EXPECT_EQ( - SequenceSortKey(TaskPriority::USER_BLOCKING, task_c_->sequenced_time), - sequence->GetSortKey()); + // Get the sort key. + const SequenceSortKey foreground_sort_key = foreground_sequence->GetSortKey(); - // Pop task C. The highest priority is still USER_BLOCKING. The task in front - // of the sequence is now task D. - sequence->TakeTask(); - sequence->Pop(); - EXPECT_EQ( - SequenceSortKey(TaskPriority::USER_BLOCKING, task_d_->sequenced_time), - sequence->GetSortKey()); + // Take the task from the sequence, so that its sequenced time is available + // for the check below. + auto take_foreground_task = foreground_sequence->TakeTask(); - // Push task E in the sequence. The highest priority is still USER_BLOCKING. - // The task in front of the sequence is still task D. - sequence->PushTask(std::move(task_e_owned_)); - EXPECT_EQ( - SequenceSortKey(TaskPriority::USER_BLOCKING, task_d_->sequenced_time), - sequence->GetSortKey()); + // Verify the sort key. + EXPECT_EQ(TaskPriority::USER_VISIBLE, foreground_sort_key.priority()); + EXPECT_EQ(take_foreground_task->sequenced_time, + foreground_sort_key.next_task_sequenced_time()); - // Pop task D. The highest priority is now from task E (BACKGROUND). The - // task in front of the sequence is now task E. - sequence->TakeTask(); - sequence->Pop(); - EXPECT_EQ(SequenceSortKey(TaskPriority::BACKGROUND, task_e_->sequenced_time), - sequence->GetSortKey()); + // Pop for correctness. + foreground_sequence->Pop(); } // Verify that a DCHECK fires if Pop() is called on a sequence whose front slot // isn't empty. -TEST_F(TaskSchedulerSequenceTest, PopNonEmptyFrontSlot) { - scoped_refptr<Sequence> sequence(new Sequence); - sequence->PushTask(std::make_unique<Task>(FROM_HERE, Bind(&DoNothing), - TaskTraits(), TimeDelta())); +TEST(TaskSchedulerSequenceTest, PopNonEmptyFrontSlot) { + scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>(); + sequence->PushTask( + Task(FROM_HERE, Bind(&DoNothing), TaskTraits(), TimeDelta())); EXPECT_DCHECK_DEATH({ sequence->Pop(); }); } // Verify that a DCHECK fires if TakeTask() is called on a sequence whose front // slot is empty. -TEST_F(TaskSchedulerSequenceTest, TakeEmptyFrontSlot) { - scoped_refptr<Sequence> sequence(new Sequence); - sequence->PushTask(std::make_unique<Task>(FROM_HERE, Bind(&DoNothing), - TaskTraits(), TimeDelta())); +TEST(TaskSchedulerSequenceTest, TakeEmptyFrontSlot) { + scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>(); + sequence->PushTask( + Task(FROM_HERE, Bind(&DoNothing), TaskTraits(), TimeDelta())); EXPECT_TRUE(sequence->TakeTask()); EXPECT_DCHECK_DEATH({ sequence->TakeTask(); }); } // Verify that a DCHECK fires if TakeTask() is called on an empty sequence. -TEST_F(TaskSchedulerSequenceTest, TakeEmptySequence) { - scoped_refptr<Sequence> sequence(new Sequence); +TEST(TaskSchedulerSequenceTest, TakeEmptySequence) { + scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>(); EXPECT_DCHECK_DEATH({ sequence->TakeTask(); }); }
diff --git a/base/task_scheduler/task.cc b/base/task_scheduler/task.cc index e4d35a3..cf21aac 100644 --- a/base/task_scheduler/task.cc +++ b/base/task_scheduler/task.cc
@@ -45,5 +45,7 @@ Task::~Task() = default; +Task& Task::operator=(Task&& other) = default; + } // namespace internal } // namespace base
diff --git a/base/task_scheduler/task.h b/base/task_scheduler/task.h index 5e7407224..3e937a8 100644 --- a/base/task_scheduler/task.h +++ b/base/task_scheduler/task.h
@@ -35,15 +35,16 @@ // Task is move-only to avoid mistakes that cause reference counts to be // accidentally bumped. Task(Task&& other) noexcept; - Task(const Task&) = delete; ~Task(); + Task& operator=(Task&& other); + // The TaskTraits of this task. - const TaskTraits traits; + TaskTraits traits; // The delay that must expire before the task runs. - const TimeDelta delay; + TimeDelta delay; // The time at which the task was inserted in its sequence. For an undelayed // task, this happens at post time. For a delayed task, this happens some @@ -62,6 +63,9 @@ // support TaskRunnerHandles. scoped_refptr<SequencedTaskRunner> sequenced_task_runner_ref; scoped_refptr<SingleThreadTaskRunner> single_thread_task_runner_ref; + + private: + DISALLOW_COPY_AND_ASSIGN(Task); }; } // namespace internal
diff --git a/base/task_scheduler/task_scheduler_impl.cc b/base/task_scheduler/task_scheduler_impl.cc index 942c844..872593e8 100644 --- a/base/task_scheduler/task_scheduler_impl.cc +++ b/base/task_scheduler/task_scheduler_impl.cc
@@ -118,7 +118,7 @@ const TaskTraits new_traits = SetUserBlockingPriorityIfNeeded(traits); GetWorkerPoolForTraits(new_traits) ->PostTaskWithSequence( - std::make_unique<Task>(from_here, std::move(task), new_traits, delay), + Task(from_here, std::move(task), new_traits, delay), MakeRefCounted<Sequence>()); }
diff --git a/base/task_scheduler/task_tracker.cc b/base/task_scheduler/task_tracker.cc index c5be7d2..ca03f7f 100644 --- a/base/task_scheduler/task_tracker.cc +++ b/base/task_scheduler/task_tracker.cc
@@ -252,17 +252,17 @@ } } -bool TaskTracker::WillPostTask(const Task* task) { - DCHECK(task); +bool TaskTracker::WillPostTask(const Task& task) { + DCHECK(task.task); - if (!BeforePostTask(task->traits.shutdown_behavior())) + if (!BeforePostTask(task.traits.shutdown_behavior())) return false; - if (task->delayed_run_time.is_null()) + if (task.delayed_run_time.is_null()) subtle::NoBarrier_AtomicIncrement(&num_incomplete_undelayed_tasks_, 1); debug::TaskAnnotator task_annotator; - task_annotator.DidQueueTask(kQueueFunctionName, *task); + task_annotator.DidQueueTask(kQueueFunctionName, task); return true; } @@ -299,7 +299,8 @@ DCHECK(sequence); // Run the next task in |sequence|. - std::unique_ptr<Task> task = sequence->TakeTask(); + Optional<Task> task = sequence->TakeTask(); + // TODO(fdoray): Support TakeTask() returning null. https://crbug.com/783309 DCHECK(task); const TaskShutdownBehavior shutdown_behavior = @@ -308,7 +309,7 @@ const bool can_run_task = BeforeRunTask(shutdown_behavior); const bool is_delayed = !task->delayed_run_time.is_null(); - RunOrSkipTask(std::move(task), sequence.get(), can_run_task); + RunOrSkipTask(std::move(task.value()), sequence.get(), can_run_task); if (can_run_task) AfterRunTask(shutdown_behavior); @@ -353,19 +354,19 @@ state_->StartShutdown(); } -void TaskTracker::RunOrSkipTask(std::unique_ptr<Task> task, +void TaskTracker::RunOrSkipTask(Task task, Sequence* sequence, bool can_run_task) { - RecordTaskLatencyHistogram(task.get()); + RecordTaskLatencyHistogram(task); const bool previous_singleton_allowed = ThreadRestrictions::SetSingletonAllowed( - task->traits.shutdown_behavior() != + task.traits.shutdown_behavior() != TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN); const bool previous_io_allowed = - ThreadRestrictions::SetIOAllowed(task->traits.may_block()); + ThreadRestrictions::SetIOAllowed(task.traits.may_block()); const bool previous_wait_allowed = ThreadRestrictions::SetWaitAllowed( - task->traits.with_base_sync_primitives()); + task.traits.with_base_sync_primitives()); { const SequenceToken& sequence_token = sequence->token(); @@ -373,7 +374,7 @@ ScopedSetSequenceTokenForCurrentThread scoped_set_sequence_token_for_current_thread(sequence_token); ScopedSetTaskPriorityForCurrentThread - scoped_set_task_priority_for_current_thread(task->traits.priority()); + scoped_set_task_priority_for_current_thread(task.traits.priority()); ScopedSetSequenceLocalStorageMapForCurrentThread scoped_set_sequence_local_storage_map_for_current_thread( sequence->sequence_local_storage()); @@ -381,35 +382,37 @@ // Set up TaskRunnerHandle as expected for the scope of the task. std::unique_ptr<SequencedTaskRunnerHandle> sequenced_task_runner_handle; std::unique_ptr<ThreadTaskRunnerHandle> single_thread_task_runner_handle; - DCHECK(!task->sequenced_task_runner_ref || - !task->single_thread_task_runner_ref); - if (task->sequenced_task_runner_ref) { + DCHECK(!task.sequenced_task_runner_ref || + !task.single_thread_task_runner_ref); + if (task.sequenced_task_runner_ref) { sequenced_task_runner_handle.reset( - new SequencedTaskRunnerHandle(task->sequenced_task_runner_ref)); - } else if (task->single_thread_task_runner_ref) { + new SequencedTaskRunnerHandle(task.sequenced_task_runner_ref)); + } else if (task.single_thread_task_runner_ref) { single_thread_task_runner_handle.reset( - new ThreadTaskRunnerHandle(task->single_thread_task_runner_ref)); + new ThreadTaskRunnerHandle(task.single_thread_task_runner_ref)); } if (can_run_task) { - TRACE_TASK_EXECUTION(kRunFunctionName, *task); + TRACE_TASK_EXECUTION(kRunFunctionName, task); const char* const execution_mode = - task->single_thread_task_runner_ref + task.single_thread_task_runner_ref ? kSingleThreadExecutionMode - : (task->sequenced_task_runner_ref ? kSequencedExecutionMode - : kParallelExecutionMode); + : (task.sequenced_task_runner_ref ? kSequencedExecutionMode + : kParallelExecutionMode); // TODO(gab): In a better world this would be tacked on as an extra arg // to the trace event generated above. This is not possible however until // http://crbug.com/652692 is resolved. TRACE_EVENT1("task_scheduler", "TaskTracker::RunTask", "task_info", std::make_unique<TaskTracingInfo>( - task->traits, execution_mode, sequence_token)); + task.traits, execution_mode, sequence_token)); - debug::TaskAnnotator().RunTask(kQueueFunctionName, task.get()); + debug::TaskAnnotator().RunTask(kQueueFunctionName, &task); } - task.reset(); + // Make sure the arguments bound to the callback are deleted within the + // scope in which the callback runs. + task.task = OnceClosure(); } ThreadRestrictions::SetWaitAllowed(previous_wait_allowed); @@ -661,11 +664,11 @@ return nullptr; } -void TaskTracker::RecordTaskLatencyHistogram(Task* task) { - const TimeDelta task_latency = TimeTicks::Now() - task->sequenced_time; - task_latency_histograms_[static_cast<int>(task->traits.priority())] - [task->traits.may_block() || - task->traits.with_base_sync_primitives() +void TaskTracker::RecordTaskLatencyHistogram(const Task& task) { + const TimeDelta task_latency = TimeTicks::Now() - task.sequenced_time; + task_latency_histograms_[static_cast<int>(task.traits.priority())] + [task.traits.may_block() || + task.traits.with_base_sync_primitives() ? 1 : 0] ->Add(task_latency.InMicroseconds());
diff --git a/base/task_scheduler/task_tracker.h b/base/task_scheduler/task_tracker.h index f249b73..f1ef25c 100644 --- a/base/task_scheduler/task_tracker.h +++ b/base/task_scheduler/task_tracker.h
@@ -108,7 +108,7 @@ // Informs this TaskTracker that |task| is about to be posted. Returns true if // this operation is allowed (|task| should be posted if-and-only-if it is). - bool WillPostTask(const Task* task); + bool WillPostTask(const Task& task); // Informs this TaskTracker that |sequence| is about to be scheduled. If this // returns |sequence|, it is expected that RunNextTask() will soon be called @@ -155,9 +155,7 @@ // have run. |sequence| is the sequence from which |task| was extracted. An // override is expected to call its parent's implementation but is free to // perform extra work before and after doing so. - virtual void RunOrSkipTask(std::unique_ptr<Task> task, - Sequence* sequence, - bool can_run_task); + virtual void RunOrSkipTask(Task task, Sequence* sequence, bool can_run_task); #if DCHECK_IS_ON() // Returns true if this context should be exempt from blocking shutdown @@ -219,7 +217,7 @@ // Records the TaskScheduler.TaskLatency.[task priority].[may block] histogram // for |task|. - void RecordTaskLatencyHistogram(Task* task); + void RecordTaskLatencyHistogram(const Task& task); // Number of tasks blocking shutdown and boolean indicating whether shutdown // has started.
diff --git a/base/task_scheduler/task_tracker_posix.cc b/base/task_scheduler/task_tracker_posix.cc index d331761..a1e3137b 100644 --- a/base/task_scheduler/task_tracker_posix.cc +++ b/base/task_scheduler/task_tracker_posix.cc
@@ -14,7 +14,7 @@ TaskTrackerPosix::TaskTrackerPosix() = default; TaskTrackerPosix::~TaskTrackerPosix() = default; -void TaskTrackerPosix::RunOrSkipTask(std::unique_ptr<Task> task, +void TaskTrackerPosix::RunOrSkipTask(Task task, Sequence* sequence, bool can_run_task) { DCHECK(watch_file_descriptor_message_loop_);
diff --git a/base/task_scheduler/task_tracker_posix.h b/base/task_scheduler/task_tracker_posix.h index 2992b9f..70c28825 100644 --- a/base/task_scheduler/task_tracker_posix.h +++ b/base/task_scheduler/task_tracker_posix.h
@@ -52,9 +52,7 @@ protected: // TaskTracker: - void RunOrSkipTask(std::unique_ptr<Task> task, - Sequence* sequence, - bool can_run_task) override; + void RunOrSkipTask(Task task, Sequence* sequence, bool can_run_task) override; private: #if DCHECK_IS_ON()
diff --git a/base/task_scheduler/task_tracker_posix_unittest.cc b/base/task_scheduler/task_tracker_posix_unittest.cc index 9ca9a913..7ee5c809 100644 --- a/base/task_scheduler/task_tracker_posix_unittest.cc +++ b/base/task_scheduler/task_tracker_posix_unittest.cc
@@ -53,12 +53,11 @@ // Verify that TaskTrackerPosix runs a Task it receives. TEST_F(TaskSchedulerTaskTrackerPosixTest, RunTask) { bool did_run = false; - auto task = std::make_unique<Task>( - FROM_HERE, - Bind([](bool* did_run) { *did_run = true; }, Unretained(&did_run)), - TaskTraits(), TimeDelta()); + Task task(FROM_HERE, + Bind([](bool* did_run) { *did_run = true; }, Unretained(&did_run)), + TaskTraits(), TimeDelta()); - EXPECT_TRUE(tracker_.WillPostTask(task.get())); + EXPECT_TRUE(tracker_.WillPostTask(task)); auto sequence = test::CreateSequenceWithTask(std::move(task)); EXPECT_EQ(sequence, tracker_.WillScheduleSequence(sequence, nullptr)); @@ -74,15 +73,14 @@ TEST_F(TaskSchedulerTaskTrackerPosixTest, FileDescriptorWatcher) { int fds[2]; ASSERT_EQ(0, pipe(fds)); - auto task = std::make_unique<Task>( - FROM_HERE, - Bind(IgnoreResult(&FileDescriptorWatcher::WatchReadable), fds[0], - Bind(&DoNothing)), - TaskTraits(), TimeDelta()); + Task task(FROM_HERE, + Bind(IgnoreResult(&FileDescriptorWatcher::WatchReadable), fds[0], + Bind(&DoNothing)), + TaskTraits(), TimeDelta()); // FileDescriptorWatcher::WatchReadable needs a SequencedTaskRunnerHandle. - task->sequenced_task_runner_ref = MakeRefCounted<NullTaskRunner>(); + task.sequenced_task_runner_ref = MakeRefCounted<NullTaskRunner>(); - EXPECT_TRUE(tracker_.WillPostTask(task.get())); + EXPECT_TRUE(tracker_.WillPostTask(task)); auto sequence = test::CreateSequenceWithTask(std::move(task)); EXPECT_EQ(sequence, tracker_.WillScheduleSequence(sequence, nullptr));
diff --git a/base/task_scheduler/task_tracker_unittest.cc b/base/task_scheduler/task_tracker_unittest.cc index 685fb35..3ae81375 100644 --- a/base/task_scheduler/task_tracker_unittest.cc +++ b/base/task_scheduler/task_tracker_unittest.cc
@@ -91,6 +91,7 @@ bool expect_post_succeeds) : SimpleThread("ThreadPostingAndRunningTask"), tracker_(tracker), + owned_task_(FROM_HERE, OnceClosure(), TaskTraits(), TimeDelta()), task_(task), action_(action), expect_post_succeeds_(expect_post_succeeds) { @@ -102,28 +103,28 @@ } ThreadPostingAndRunningTask(TaskTracker* tracker, - std::unique_ptr<Task> task, + Task task, Action action, bool expect_post_succeeds) : SimpleThread("ThreadPostingAndRunningTask"), tracker_(tracker), - task_(task.get()), owned_task_(std::move(task)), + task_(&owned_task_), action_(action), expect_post_succeeds_(expect_post_succeeds) { - EXPECT_TRUE(task_); + EXPECT_TRUE(owned_task_.task); } private: void Run() override { bool post_succeeded = true; if (action_ == Action::WILL_POST || action_ == Action::WILL_POST_AND_RUN) { - post_succeeded = tracker_->WillPostTask(task_); + post_succeeded = tracker_->WillPostTask(*task_); EXPECT_EQ(expect_post_succeeds_, post_succeeded); } if (post_succeeded && (action_ == Action::RUN || action_ == Action::WILL_POST_AND_RUN)) { - EXPECT_TRUE(owned_task_); + EXPECT_TRUE(owned_task_.task); testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer; @@ -139,8 +140,8 @@ } TaskTracker* const tracker_; - Task* const task_; - std::unique_ptr<Task> owned_task_; + Task owned_task_; + Task* task_; const Action action_; const bool expect_post_succeeds_; @@ -166,14 +167,14 @@ TaskSchedulerTaskTrackerTest() = default; // Creates a task with |shutdown_behavior|. - std::unique_ptr<Task> CreateTask(TaskShutdownBehavior shutdown_behavior) { - return std::make_unique<Task>( + Task CreateTask(TaskShutdownBehavior shutdown_behavior) { + return Task( FROM_HERE, Bind(&TaskSchedulerTaskTrackerTest::RunTaskCallback, Unretained(this)), TaskTraits(shutdown_behavior), TimeDelta()); } - void DispatchAndRunTaskWithTracker(std::unique_ptr<Task> task) { + void DispatchAndRunTaskWithTracker(Task task) { auto sequence = tracker_.WillScheduleSequence( test::CreateSequenceWithTask(std::move(task)), &never_notified_observer_); @@ -278,10 +279,10 @@ } // namespace TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunBeforeShutdown) { - std::unique_ptr<Task> task(CreateTask(GetParam())); + Task task(CreateTask(GetParam())); // Inform |task_tracker_| that |task| will be posted. - EXPECT_TRUE(tracker_.WillPostTask(task.get())); + EXPECT_TRUE(tracker_.WillPostTask(task)); // Run the task. EXPECT_EQ(0U, NumTasksExecuted()); @@ -300,7 +301,7 @@ WaitableEvent::InitialState::NOT_SIGNALED); WaitableEvent task_barrier(WaitableEvent::ResetPolicy::AUTOMATIC, WaitableEvent::InitialState::NOT_SIGNALED); - auto blocked_task = std::make_unique<Task>( + Task blocked_task( FROM_HERE, Bind( [](WaitableEvent* task_running, WaitableEvent* task_barrier) { @@ -311,7 +312,7 @@ TaskTraits(WithBaseSyncPrimitives(), GetParam()), TimeDelta()); // Inform |task_tracker_| that |blocked_task| will be posted. - EXPECT_TRUE(tracker_.WillPostTask(blocked_task.get())); + EXPECT_TRUE(tracker_.WillPostTask(blocked_task)); // Create a thread to run the task. Wait until the task starts running. ThreadPostingAndRunningTask thread_running_task( @@ -342,14 +343,13 @@ TEST_P(TaskSchedulerTaskTrackerTest, WillPostBeforeShutdownRunDuringShutdown) { // Inform |task_tracker_| that a task will be posted. - std::unique_ptr<Task> task(CreateTask(GetParam())); - EXPECT_TRUE(tracker_.WillPostTask(task.get())); + Task task(CreateTask(GetParam())); + EXPECT_TRUE(tracker_.WillPostTask(task)); // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to // block shutdown. - std::unique_ptr<Task> block_shutdown_task( - CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); - EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get())); + Task block_shutdown_task(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); + EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task)); // Call Shutdown() asynchronously. CallShutdownAsync(); @@ -372,8 +372,8 @@ TEST_P(TaskSchedulerTaskTrackerTest, WillPostBeforeShutdownRunAfterShutdown) { // Inform |task_tracker_| that a task will be posted. - std::unique_ptr<Task> task(CreateTask(GetParam())); - EXPECT_TRUE(tracker_.WillPostTask(task.get())); + Task task(CreateTask(GetParam())); + EXPECT_TRUE(tracker_.WillPostTask(task)); // Call Shutdown() asynchronously. CallShutdownAsync(); @@ -402,9 +402,8 @@ TEST_P(TaskSchedulerTaskTrackerTest, WillPostAndRunDuringShutdown) { // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to // block shutdown. - std::unique_ptr<Task> block_shutdown_task( - CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); - EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get())); + Task block_shutdown_task(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); + EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task)); // Call Shutdown() asynchronously. CallShutdownAsync(); @@ -412,8 +411,8 @@ if (GetParam() == TaskShutdownBehavior::BLOCK_SHUTDOWN) { // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted. - std::unique_ptr<Task> task(CreateTask(GetParam())); - EXPECT_TRUE(tracker_.WillPostTask(task.get())); + Task task(CreateTask(GetParam())); + EXPECT_TRUE(tracker_.WillPostTask(task)); // Run the BLOCK_SHUTDOWN task. EXPECT_EQ(0U, NumTasksExecuted()); @@ -421,8 +420,8 @@ EXPECT_EQ(1U, NumTasksExecuted()); } else { // It shouldn't be allowed to post a non BLOCK_SHUTDOWN task. - std::unique_ptr<Task> task(CreateTask(GetParam())); - EXPECT_FALSE(tracker_.WillPostTask(task.get())); + Task task(CreateTask(GetParam())); + EXPECT_FALSE(tracker_.WillPostTask(task)); // Don't try to run the task, because it wasn't allowed to be posted. } @@ -438,10 +437,10 @@ TEST_P(TaskSchedulerTaskTrackerTest, WillPostAfterShutdown) { tracker_.Shutdown(); - std::unique_ptr<Task> task(CreateTask(GetParam())); + Task task(CreateTask(GetParam())); // |task_tracker_| shouldn't allow a task to be posted after shutdown. - EXPECT_FALSE(tracker_.WillPostTask(task.get())); + EXPECT_FALSE(tracker_.WillPostTask(task)); } // Verify that BLOCK_SHUTDOWN and SKIP_ON_SHUTDOWN tasks can @@ -450,10 +449,9 @@ const bool can_use_singletons = (GetParam() != TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN); - std::unique_ptr<Task> task( - new Task(FROM_HERE, BindOnce(&ThreadRestrictions::AssertSingletonAllowed), - TaskTraits(GetParam()), TimeDelta())); - EXPECT_TRUE(tracker_.WillPostTask(task.get())); + Task task(FROM_HERE, BindOnce(&ThreadRestrictions::AssertSingletonAllowed), + TaskTraits(GetParam()), TimeDelta()); + EXPECT_TRUE(tracker_.WillPostTask(task)); // Set the singleton allowed bit to the opposite of what it is expected to be // when |tracker| runs |task| to verify that |tracker| actually sets the @@ -473,31 +471,29 @@ // Unset the IO allowed bit. Expect TaskTracker to set it before running a // task with the MayBlock() trait. ThreadRestrictions::SetIOAllowed(false); - auto task_with_may_block = - std::make_unique<Task>(FROM_HERE, Bind([]() { - // Shouldn't fail. - AssertBlockingAllowed(); - }), - TaskTraits(MayBlock(), GetParam()), TimeDelta()); - EXPECT_TRUE(tracker_.WillPostTask(task_with_may_block.get())); + Task task_with_may_block(FROM_HERE, Bind([]() { + // Shouldn't fail. + AssertBlockingAllowed(); + }), + TaskTraits(MayBlock(), GetParam()), TimeDelta()); + EXPECT_TRUE(tracker_.WillPostTask(task_with_may_block)); DispatchAndRunTaskWithTracker(std::move(task_with_may_block)); // Set the IO allowed bit. Expect TaskTracker to unset it before running a // task without the MayBlock() trait. ThreadRestrictions::SetIOAllowed(true); - auto task_without_may_block = std::make_unique<Task>( + Task task_without_may_block( FROM_HERE, Bind([]() { EXPECT_DCHECK_DEATH({ AssertBlockingAllowed(); }); }), TaskTraits(GetParam()), TimeDelta()); - EXPECT_TRUE(tracker_.WillPostTask(task_without_may_block.get())); + EXPECT_TRUE(tracker_.WillPostTask(task_without_may_block)); DispatchAndRunTaskWithTracker(std::move(task_without_may_block)); } -static void RunTaskRunnerHandleVerificationTask( - TaskTracker* tracker, - std::unique_ptr<Task> verify_task) { +static void RunTaskRunnerHandleVerificationTask(TaskTracker* tracker, + Task verify_task) { // Pretend |verify_task| is posted to respect TaskTracker's contract. - EXPECT_TRUE(tracker->WillPostTask(verify_task.get())); + EXPECT_TRUE(tracker->WillPostTask(verify_task)); // Confirm that the test conditions are right (no TaskRunnerHandles set // already). @@ -524,9 +520,8 @@ TEST_P(TaskSchedulerTaskTrackerTest, TaskRunnerHandleIsNotSetOnParallel) { // Create a task that will verify that TaskRunnerHandles are not set in its // scope per no TaskRunner ref being set to it. - std::unique_ptr<Task> verify_task( - new Task(FROM_HERE, BindOnce(&VerifyNoTaskRunnerHandle), - TaskTraits(GetParam()), TimeDelta())); + Task verify_task(FROM_HERE, BindOnce(&VerifyNoTaskRunnerHandle), + TaskTraits(GetParam()), TimeDelta()); RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task)); } @@ -545,12 +540,11 @@ // Create a task that will verify that SequencedTaskRunnerHandle is properly // set to |test_task_runner| in its scope per |sequenced_task_runner_ref| // being set to it. - std::unique_ptr<Task> verify_task( - new Task(FROM_HERE, - BindOnce(&VerifySequencedTaskRunnerHandle, - Unretained(test_task_runner.get())), - TaskTraits(GetParam()), TimeDelta())); - verify_task->sequenced_task_runner_ref = test_task_runner; + Task verify_task(FROM_HERE, + BindOnce(&VerifySequencedTaskRunnerHandle, + Unretained(test_task_runner.get())), + TaskTraits(GetParam()), TimeDelta()); + verify_task.sequenced_task_runner_ref = test_task_runner; RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task)); } @@ -571,12 +565,11 @@ // Create a task that will verify that ThreadTaskRunnerHandle is properly set // to |test_task_runner| in its scope per |single_thread_task_runner_ref| // being set on it. - std::unique_ptr<Task> verify_task( - new Task(FROM_HERE, - BindOnce(&VerifyThreadTaskRunnerHandle, - Unretained(test_task_runner.get())), - TaskTraits(GetParam()), TimeDelta())); - verify_task->single_thread_task_runner_ref = test_task_runner; + Task verify_task(FROM_HERE, + BindOnce(&VerifyThreadTaskRunnerHandle, + Unretained(test_task_runner.get())), + TaskTraits(GetParam()), TimeDelta()); + verify_task.single_thread_task_runner_ref = test_task_runner; RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task)); } @@ -584,15 +577,15 @@ TEST_P(TaskSchedulerTaskTrackerTest, FlushPendingDelayedTask) { const Task delayed_task(FROM_HERE, BindOnce(&DoNothing), TaskTraits(GetParam()), TimeDelta::FromDays(1)); - tracker_.WillPostTask(&delayed_task); + tracker_.WillPostTask(delayed_task); // Flush() should return even if the delayed task didn't run. tracker_.Flush(); } TEST_P(TaskSchedulerTaskTrackerTest, FlushPendingUndelayedTask) { - auto undelayed_task = std::make_unique<Task>( - FROM_HERE, Bind(&DoNothing), TaskTraits(GetParam()), TimeDelta()); - tracker_.WillPostTask(undelayed_task.get()); + Task undelayed_task(FROM_HERE, Bind(&DoNothing), TaskTraits(GetParam()), + TimeDelta()); + tracker_.WillPostTask(undelayed_task); // Flush() shouldn't return before the undelayed task runs. CallFlushAsync(); @@ -605,9 +598,9 @@ } TEST_P(TaskSchedulerTaskTrackerTest, PostTaskDuringFlush) { - auto undelayed_task = std::make_unique<Task>( - FROM_HERE, Bind(&DoNothing), TaskTraits(GetParam()), TimeDelta()); - tracker_.WillPostTask(undelayed_task.get()); + Task undelayed_task(FROM_HERE, Bind(&DoNothing), TaskTraits(GetParam()), + TimeDelta()); + tracker_.WillPostTask(undelayed_task); // Flush() shouldn't return before the undelayed task runs. CallFlushAsync(); @@ -615,9 +608,9 @@ VERIFY_ASYNC_FLUSH_IN_PROGRESS(); // Simulate posting another undelayed task. - auto other_undelayed_task = std::make_unique<Task>( - FROM_HERE, Bind(&DoNothing), TaskTraits(GetParam()), TimeDelta()); - tracker_.WillPostTask(other_undelayed_task.get()); + Task other_undelayed_task(FROM_HERE, Bind(&DoNothing), TaskTraits(GetParam()), + TimeDelta()); + tracker_.WillPostTask(other_undelayed_task); // Run the first undelayed task. DispatchAndRunTaskWithTracker(std::move(undelayed_task)); @@ -633,13 +626,12 @@ TEST_P(TaskSchedulerTaskTrackerTest, RunDelayedTaskDuringFlush) { // Simulate posting a delayed and an undelayed task. - auto delayed_task = - std::make_unique<Task>(FROM_HERE, Bind(&DoNothing), - TaskTraits(GetParam()), TimeDelta::FromDays(1)); - tracker_.WillPostTask(delayed_task.get()); - auto undelayed_task = std::make_unique<Task>( - FROM_HERE, Bind(&DoNothing), TaskTraits(GetParam()), TimeDelta()); - tracker_.WillPostTask(undelayed_task.get()); + Task delayed_task(FROM_HERE, Bind(&DoNothing), TaskTraits(GetParam()), + TimeDelta::FromDays(1)); + tracker_.WillPostTask(delayed_task); + Task undelayed_task(FROM_HERE, Bind(&DoNothing), TaskTraits(GetParam()), + TimeDelta()); + tracker_.WillPostTask(undelayed_task); // Flush() shouldn't return before the undelayed task runs. CallFlushAsync(); @@ -666,9 +658,9 @@ return; // Simulate posting a task. - auto undelayed_task = std::make_unique<Task>( - FROM_HERE, Bind(&DoNothing), TaskTraits(GetParam()), TimeDelta()); - tracker_.WillPostTask(undelayed_task.get()); + Task undelayed_task(FROM_HERE, Bind(&DoNothing), TaskTraits(GetParam()), + TimeDelta()); + tracker_.WillPostTask(undelayed_task); // Shutdown() should return immediately since there are no pending // BLOCK_SHUTDOWN tasks. @@ -684,9 +676,9 @@ return; // Simulate posting a task. - auto undelayed_task = std::make_unique<Task>( - FROM_HERE, Bind(&DoNothing), TaskTraits(GetParam()), TimeDelta()); - tracker_.WillPostTask(undelayed_task.get()); + Task undelayed_task(FROM_HERE, Bind(&DoNothing), TaskTraits(GetParam()), + TimeDelta()); + tracker_.WillPostTask(undelayed_task); // Flush() shouldn't return before the undelayed task runs or // shutdown completes. @@ -729,10 +721,9 @@ scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>(); const SequenceToken sequence_token = sequence->token(); - auto task = std::make_unique<Task>(FROM_HERE, - Bind(&ExpectSequenceToken, sequence_token), - TaskTraits(), TimeDelta()); - tracker_.WillPostTask(task.get()); + Task task(FROM_HERE, Bind(&ExpectSequenceToken, sequence_token), TaskTraits(), + TimeDelta()); + tracker_.WillPostTask(task); sequence->PushTask(std::move(task)); @@ -778,25 +769,32 @@ TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostBeforeShutdownAndRunDuringShutdown) { // Post tasks asynchronously. - std::vector<std::unique_ptr<Task>> tasks; - std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> post_threads; - + std::vector<Task> tasks_continue_on_shutdown; + std::vector<Task> tasks_skip_on_shutdown; + std::vector<Task> tasks_block_shutdown; for (size_t i = 0; i < kLoadTestNumIterations; ++i) { - tasks.push_back(CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); + tasks_continue_on_shutdown.push_back( + CreateTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); + tasks_skip_on_shutdown.push_back( + CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); + tasks_block_shutdown.push_back( + CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); + } + + std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> post_threads; + for (size_t i = 0; i < kLoadTestNumIterations; ++i) { post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( - &tracker_, tasks.back().get(), + &tracker_, &tasks_continue_on_shutdown[i], ThreadPostingAndRunningTask::Action::WILL_POST, true)); post_threads.back()->Start(); - tasks.push_back(CreateTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( - &tracker_, tasks.back().get(), + &tracker_, &tasks_skip_on_shutdown[i], ThreadPostingAndRunningTask::Action::WILL_POST, true)); post_threads.back()->Start(); - tasks.push_back(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); post_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( - &tracker_, tasks.back().get(), + &tracker_, &tasks_block_shutdown[i], ThreadPostingAndRunningTask::Action::WILL_POST, true)); post_threads.back()->Start(); } @@ -809,11 +807,20 @@ // Run tasks asynchronously. std::vector<std::unique_ptr<ThreadPostingAndRunningTask>> run_threads; - - for (auto& task : tasks) { + for (size_t i = 0; i < kLoadTestNumIterations; ++i) { run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( - &tracker_, std::move(task), ThreadPostingAndRunningTask::Action::RUN, - false)); + &tracker_, std::move(tasks_continue_on_shutdown[i]), + ThreadPostingAndRunningTask::Action::RUN, false)); + run_threads.back()->Start(); + + run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( + &tracker_, std::move(tasks_skip_on_shutdown[i]), + ThreadPostingAndRunningTask::Action::RUN, false)); + run_threads.back()->Start(); + + run_threads.push_back(std::make_unique<ThreadPostingAndRunningTask>( + &tracker_, std::move(tasks_block_shutdown[i]), + ThreadPostingAndRunningTask::Action::RUN, false)); run_threads.back()->Start(); } @@ -829,9 +836,8 @@ TEST_F(TaskSchedulerTaskTrackerTest, LoadWillPostAndRunDuringShutdown) { // Inform |task_tracker_| that a BLOCK_SHUTDOWN task will be posted just to // block shutdown. - std::unique_ptr<Task> block_shutdown_task( - CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); - EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task.get())); + Task block_shutdown_task(CreateTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); + EXPECT_TRUE(tracker_.WillPostTask(block_shutdown_task)); // Call Shutdown() asynchronously. CallShutdownAsync(); @@ -874,12 +880,10 @@ // Verify that RunNextTask() returns the sequence from which it ran a task when // it can be rescheduled. TEST_F(TaskSchedulerTaskTrackerTest, RunNextTaskReturnsSequenceToReschedule) { - auto task_1 = std::make_unique<Task>(FROM_HERE, BindOnce(&DoNothing), - TaskTraits(), TimeDelta()); - EXPECT_TRUE(tracker_.WillPostTask(task_1.get())); - auto task_2 = std::make_unique<Task>(FROM_HERE, BindOnce(&DoNothing), - TaskTraits(), TimeDelta()); - EXPECT_TRUE(tracker_.WillPostTask(task_2.get())); + Task task_1(FROM_HERE, BindOnce(&DoNothing), TaskTraits(), TimeDelta()); + EXPECT_TRUE(tracker_.WillPostTask(task_1)); + Task task_2(FROM_HERE, BindOnce(&DoNothing), TaskTraits(), TimeDelta()); + EXPECT_TRUE(tracker_.WillPostTask(task_2)); scoped_refptr<Sequence> sequence = test::CreateSequenceWithTask(std::move(task_1)); @@ -904,10 +908,9 @@ std::vector<scoped_refptr<Sequence>> scheduled_sequences; testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer; for (int i = 0; i < kMaxNumDispatchedBackgroundSequences; ++i) { - auto task = std::make_unique<Task>(FROM_HERE, BindOnce(&DoNothing), - TaskTraits(TaskPriority::BACKGROUND), - TimeDelta()); - EXPECT_TRUE(tracker.WillPostTask(task.get())); + Task task(FROM_HERE, BindOnce(&DoNothing), + TaskTraits(TaskPriority::BACKGROUND), TimeDelta()); + EXPECT_TRUE(tracker.WillPostTask(task)); scoped_refptr<Sequence> sequence = test::CreateSequenceWithTask(std::move(task)); EXPECT_EQ(sequence, @@ -925,12 +928,12 @@ std::vector<scoped_refptr<Sequence>> extra_sequences; for (int i = 0; i < kMaxNumDispatchedBackgroundSequences; ++i) { extra_tasks_did_run.push_back(std::make_unique<bool>()); - auto extra_task = std::make_unique<Task>( + Task extra_task( FROM_HERE, BindOnce([](bool* extra_task_did_run) { *extra_task_did_run = true; }, Unretained(extra_tasks_did_run.back().get())), TaskTraits(TaskPriority::BACKGROUND), TimeDelta()); - EXPECT_TRUE(tracker.WillPostTask(extra_task.get())); + EXPECT_TRUE(tracker.WillPostTask(extra_task)); extra_sequences.push_back( test::CreateSequenceWithTask(std::move(extra_task))); extra_observers.push_back( @@ -983,10 +986,9 @@ // Simulate posting a background task and scheduling the associated sequence. // This should succeed. bool task_a_1_did_run = false; - auto task_a_1 = std::make_unique<Task>( - FROM_HERE, BindOnce(&SetBool, Unretained(&task_a_1_did_run)), - TaskTraits(TaskPriority::BACKGROUND), TimeDelta()); - EXPECT_TRUE(tracker.WillPostTask(task_a_1.get())); + Task task_a_1(FROM_HERE, BindOnce(&SetBool, Unretained(&task_a_1_did_run)), + TaskTraits(TaskPriority::BACKGROUND), TimeDelta()); + EXPECT_TRUE(tracker.WillPostTask(task_a_1)); scoped_refptr<Sequence> sequence_a = test::CreateSequenceWithTask(std::move(task_a_1)); EXPECT_EQ(sequence_a, @@ -996,28 +998,24 @@ // sequence. This should fail because the maximum number of background // sequences that can be scheduled concurrently is already reached. bool task_b_1_did_run = false; - auto task_b_1 = std::make_unique<Task>( - FROM_HERE, BindOnce(&SetBool, Unretained(&task_b_1_did_run)), - TaskTraits(TaskPriority::BACKGROUND), TimeDelta()); - Task* const task_b_1_raw = task_b_1.get(); - EXPECT_TRUE(tracker.WillPostTask(task_b_1_raw)); + Task task_b_1(FROM_HERE, BindOnce(&SetBool, Unretained(&task_b_1_did_run)), + TaskTraits(TaskPriority::BACKGROUND), TimeDelta()); + EXPECT_TRUE(tracker.WillPostTask(task_b_1)); scoped_refptr<Sequence> sequence_b = test::CreateSequenceWithTask(std::move(task_b_1)); testing::StrictMock<MockCanScheduleSequenceObserver> task_b_1_observer; EXPECT_FALSE(tracker.WillScheduleSequence(sequence_b, &task_b_1_observer)); + // Wait to be sure that the sequence time of |task_a_2| is after the sequenced + // time of |task_b_1|. + PlatformThread::Sleep(TestTimeouts::tiny_timeout()); + // Post an extra background task in |sequence_a|. bool task_a_2_did_run = false; - auto task_a_2 = std::make_unique<Task>( - FROM_HERE, BindOnce(&SetBool, Unretained(&task_a_2_did_run)), - TaskTraits(TaskPriority::BACKGROUND), TimeDelta()); - Task* const task_a_2_raw = task_a_2.get(); - EXPECT_TRUE(tracker.WillPostTask(task_a_2_raw)); + Task task_a_2(FROM_HERE, BindOnce(&SetBool, Unretained(&task_a_2_did_run)), + TaskTraits(TaskPriority::BACKGROUND), TimeDelta()); + EXPECT_TRUE(tracker.WillPostTask(task_a_2)); sequence_a->PushTask(std::move(task_a_2)); - // Make sure that the sequenced time of |task_a_2| is after the sequenced time - // of |task_b_1|. - task_a_2_raw->sequenced_time = - task_b_1_raw->sequenced_time + TimeDelta::FromSeconds(1); // Run the first task in |sequence_a|. RunNextTask() should return nullptr // since |sequence_a| can't be rescheduled immediately. |task_b_1_observer| @@ -1057,12 +1055,12 @@ // Waiting is allowed by default. Expect TaskTracker to disallow it before // running a task without the WithBaseSyncPrimitives() trait. internal::AssertBaseSyncPrimitivesAllowed(); - auto task_without_sync_primitives = std::make_unique<Task>( + Task task_without_sync_primitives( FROM_HERE, Bind([]() { EXPECT_DCHECK_DEATH({ internal::AssertBaseSyncPrimitivesAllowed(); }); }), TaskTraits(), TimeDelta()); - EXPECT_TRUE(tracker.WillPostTask(task_without_sync_primitives.get())); + EXPECT_TRUE(tracker.WillPostTask(task_without_sync_primitives)); testing::StrictMock<MockCanScheduleSequenceObserver> never_notified_observer; auto sequence_without_sync_primitives = tracker.WillScheduleSequence( @@ -1075,13 +1073,13 @@ // Disallow waiting. Expect TaskTracker to allow it before running a task // with the WithBaseSyncPrimitives() trait. ThreadRestrictions::DisallowWaiting(); - auto task_with_sync_primitives = std::make_unique<Task>( + Task task_with_sync_primitives( FROM_HERE, Bind([]() { // Shouldn't fail. internal::AssertBaseSyncPrimitivesAllowed(); }), TaskTraits(WithBaseSyncPrimitives()), TimeDelta()); - EXPECT_TRUE(tracker.WillPostTask(task_with_sync_primitives.get())); + EXPECT_TRUE(tracker.WillPostTask(task_with_sync_primitives)); auto sequence_with_sync_primitives = tracker.WillScheduleSequence( test::CreateSequenceWithTask(std::move(task_with_sync_primitives)), &never_notified_observer); @@ -1142,9 +1140,8 @@ "MayBlock"}}; for (const auto& test : tests) { - auto task = std::make_unique<Task>(FROM_HERE, Bind(&DoNothing), test.traits, - TimeDelta()); - ASSERT_TRUE(tracker.WillPostTask(task.get())); + Task task(FROM_HERE, Bind(&DoNothing), test.traits, TimeDelta()); + ASSERT_TRUE(tracker.WillPostTask(task)); HistogramTester tester;
diff --git a/base/task_scheduler/test_utils.cc b/base/task_scheduler/test_utils.cc index 963fdf2..e8d4c99 100644 --- a/base/task_scheduler/test_utils.cc +++ b/base/task_scheduler/test_utils.cc
@@ -13,7 +13,7 @@ namespace internal { namespace test { -scoped_refptr<Sequence> CreateSequenceWithTask(std::unique_ptr<Task> task) { +scoped_refptr<Sequence> CreateSequenceWithTask(Task task) { scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>(); sequence->PushTask(std::move(task)); return sequence;
diff --git a/base/task_scheduler/test_utils.h b/base/task_scheduler/test_utils.h index 8e163c2..d7903d37 100644 --- a/base/task_scheduler/test_utils.h +++ b/base/task_scheduler/test_utils.h
@@ -5,8 +5,6 @@ #ifndef BASE_TASK_SCHEDULER_TEST_UTILS_H_ #define BASE_TASK_SCHEDULER_TEST_UTILS_H_ -#include <memory> - #include "base/memory/ref_counted.h" #include "base/task_runner.h" @@ -25,7 +23,7 @@ enum class ExecutionMode { PARALLEL, SEQUENCED, SINGLE_THREADED }; // Creates a Sequence and pushes |task| to it. Returns that sequence. -scoped_refptr<Sequence> CreateSequenceWithTask(std::unique_ptr<Task> task); +scoped_refptr<Sequence> CreateSequenceWithTask(Task task); // Creates a TaskRunner that posts tasks to |worker_pool| with the // |execution_mode| execution mode and the WithBaseSyncPrimitives() trait.
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java b/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java index bd23f26..353f72b 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java +++ b/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java
@@ -5,6 +5,7 @@ package org.chromium.base.test.util; import android.content.Context; +import android.text.TextUtils; import org.junit.Assert; import org.junit.Rule; @@ -22,6 +23,7 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -54,6 +56,8 @@ * Note that this class should never be instantiated. */ public final class CommandLineFlags { + private static final String DISABLE_FEATURES = "disable-features"; + private static final String ENABLE_FEATURES = "enable-features"; /** * Adds command-line flags to the {@link org.chromium.base.CommandLine} for this test. @@ -88,15 +92,33 @@ Assert.assertNotNull("Unable to get a non-null target context.", targetContext); CommandLine.reset(); BaseChromiumApplication.initCommandLine(targetContext); + Set<String> enableFeatures = new HashSet<String>(); + Set<String> disableFeatures = new HashSet<String>(); Set<String> flags = getFlags(element); for (String flag : flags) { String[] parsedFlags = flag.split("=", 2); if (parsedFlags.length == 1) { CommandLine.getInstance().appendSwitch(flag); + } else if (ENABLE_FEATURES.equals(parsedFlags[0])) { + // We collect enable/disable features flags separately and aggregate them because + // they may be specified multiple times, in which case the values will trample each + // other. + Collections.addAll(enableFeatures, parsedFlags[1].split(",")); + } else if (DISABLE_FEATURES.equals(parsedFlags[0])) { + Collections.addAll(disableFeatures, parsedFlags[1].split(",")); } else { CommandLine.getInstance().appendSwitchWithValue(parsedFlags[0], parsedFlags[1]); } } + + if (enableFeatures.size() > 0) { + CommandLine.getInstance().appendSwitchWithValue( + ENABLE_FEATURES, TextUtils.join(",", enableFeatures)); + } + if (disableFeatures.size() > 0) { + CommandLine.getInstance().appendSwitchWithValue( + DISABLE_FEATURES, TextUtils.join(",", disableFeatures)); + } } private static Set<String> getFlags(AnnotatedElement type) {
diff --git a/base/test/scoped_task_environment.cc b/base/test/scoped_task_environment.cc index 2b80000..a9fe5ac 100644 --- a/base/test/scoped_task_environment.cc +++ b/base/test/scoped_task_environment.cc
@@ -62,7 +62,7 @@ friend class ScopedTaskEnvironment; // internal::TaskSchedulerImpl::TaskTrackerImpl: - void RunOrSkipTask(std::unique_ptr<internal::Task> task, + void RunOrSkipTask(internal::Task task, internal::Sequence* sequence, bool can_run_task) override; @@ -258,7 +258,7 @@ } void ScopedTaskEnvironment::TestTaskTracker::RunOrSkipTask( - std::unique_ptr<internal::Task> task, + internal::Task task, internal::Sequence* sequence, bool can_run_task) { {
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 95128a1..a894a39 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -101,6 +101,24 @@ # Strip the debug info of symbols file in lib.unstripped to reduce size. strip_debug_info = false + + # Path to an AFDO profile to use while building with clang, if any. Empty + # implies none. + # + # Please note that you need to be very careful about changing your profile at + # the moment. See the `BUG(gbiv)` comment later in this file. + clang_sample_profile_path = "" + + # Some configurations have default sample profiles. If this is true and + # clang_sample_profile_path is empty, we'll fall back to the default. + clang_use_default_sample_profile = + is_official_build && defined(clang_default_afdo_profile) + + # Whether to assert to the compiler that the AFDO profiles are accurate. + # True will cause the compiler to optimize uncovered functions for size + # (despite passing -O2 or -O3), which reduces binary size by quite a bit, + # potentially at the cost of some performance. + clang_sample_profile_is_accurate = true } declare_args() { @@ -197,6 +215,34 @@ # -------------------------------- cflags += [ "-fno-strict-aliasing" ] # See http://crbug.com/32204 + # AFDO on clang. Clang doesn't seem to suffer from the bug that caused GCC's + # AFDO to be split into its own config, so this isn't part of that config. + # + # Since we only profile the browser, skip it if we're building host tools. + # + # XXX(gbiv): There is currently *no* dependency between the profile we use + # and the compilations/links that we do. So, if the profile gets updated, + # the user has to manually clean build artifacts. CL:827560 should fix this + # by allowing us to specify `inputs` here, but until then, the only "good" + # workaround is changing your profile name each time you update the profile. + if (is_clang && current_toolchain == default_toolchain) { + _sample_path = "" + if (clang_sample_profile_path != "") { + _sample_path = clang_sample_profile_path + } else if (clang_use_default_sample_profile) { + assert(defined(clang_default_afdo_profile), + "This platform has no default sample profiles") + _sample_path = clang_default_afdo_profile + } + + if (_sample_path != "") { + cflags += [ "-fprofile-sample-use=${_sample_path}" ] + if (clang_sample_profile_is_accurate) { + cflags += [ "-fprofile-sample-accurate" ] + } + } + } + # Stack protection. if (is_mac) { # The strong variant of the stack protector significantly increases
diff --git a/build/install-build-deps.sh b/build/install-build-deps.sh index 0082ca4..cae0a6a 100755 --- a/build/install-build-deps.sh +++ b/build/install-build-deps.sh
@@ -169,11 +169,9 @@ libcap-dev libcups2-dev libcurl4-gnutls-dev - libdconf-dev libdrm-dev libelf-dev libffi-dev - libgconf2-dev libglib2.0-dev libglu1-mesa-dev libgnome-keyring-dev @@ -236,7 +234,6 @@ libcairo2 libcap2 libcups2 - libdconf1 libexpat1 libffi6 libfontconfig1 @@ -421,9 +418,7 @@ libasound2:i386 libcap2:i386 libelf-dev:i386 - libdconf1:i386 libfontconfig1:i386 - libgconf-2-4:i386 libglib2.0-0:i386 libgpm2:i386 libgtk2.0-0:i386
diff --git a/build/linux/sysroot_scripts/packagelist.stretch.amd64 b/build/linux/sysroot_scripts/packagelist.stretch.amd64 index 537faa6..aac388b 100644 --- a/build/linux/sysroot_scripts/packagelist.stretch.amd64 +++ b/build/linux/sysroot_scripts/packagelist.stretch.amd64
@@ -16,19 +16,20 @@ http://ftp.us.debian.org/debian/pool/main/c/cairo/libcairo2-dev_1.14.8-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/c/cairo/libcairo-gobject2_1.14.8-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/c/cairo/libcairo-script-interpreter2_1.14.8-1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/c/colord/libcolord2_1.3.3-2_amd64.deb http://ftp.us.debian.org/debian/pool/main/c/cups/libcups2_2.2.1-8_amd64.deb http://ftp.us.debian.org/debian/pool/main/c/cups/libcups2-dev_2.2.1-8_amd64.deb http://ftp.us.debian.org/debian/pool/main/c/cups/libcupsimage2_2.2.1-8_amd64.deb http://ftp.us.debian.org/debian/pool/main/c/cups/libcupsimage2-dev_2.2.1-8_amd64.deb +http://ftp.us.debian.org/debian/pool/main/d/db5.3/libdb5.3_5.3.28-12+deb9u1_amd64.deb http://ftp.us.debian.org/debian/pool/main/d/dbus-glib/libdbus-glib-1-2_0.108-2_amd64.deb -http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-3_1.10.22-0+deb9u1_amd64.deb -http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-dev_1.10.22-0+deb9u1_amd64.deb -http://ftp.us.debian.org/debian/pool/main/d/d-conf/libdconf1_0.26.0-2+b1_amd64.deb -http://ftp.us.debian.org/debian/pool/main/d/d-conf/libdconf-dev_0.26.0-2+b1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-3_1.10.24-0+deb9u1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-dev_1.10.24-0+deb9u1_amd64.deb http://ftp.us.debian.org/debian/pool/main/e/e2fsprogs/comerr-dev_2.1-1.43.4-2_amd64.deb http://ftp.us.debian.org/debian/pool/main/e/e2fsprogs/libcomerr2_1.43.4-2_amd64.deb http://ftp.us.debian.org/debian/pool/main/e/elfutils/libelf1_0.168-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/e/elfutils/libelf-dev_0.168-1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/f/flac/libflac8_1.3.2-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/f/fontconfig/libfontconfig1_2.11.0-6.7+b1_amd64.deb http://ftp.us.debian.org/debian/pool/main/f/fontconfig/libfontconfig1-dev_2.11.0-6.7+b1_amd64.deb http://ftp.us.debian.org/debian/pool/main/f/freetype/libfreetype6_2.6.3-3.2_amd64.deb @@ -47,11 +48,9 @@ http://ftp.us.debian.org/debian/pool/main/g/gcc-6/libstdc++-6-dev_6.3.0-18_amd64.deb http://ftp.us.debian.org/debian/pool/main/g/gcc-6/libtsan0_6.3.0-18_amd64.deb http://ftp.us.debian.org/debian/pool/main/g/gcc-6/libubsan0_6.3.0-18_amd64.deb -http://ftp.us.debian.org/debian/pool/main/g/gconf/libgconf2-4_3.2.6-4+b1_amd64.deb -http://ftp.us.debian.org/debian/pool/main/g/gconf/libgconf-2-4_3.2.6-4+b1_amd64.deb -http://ftp.us.debian.org/debian/pool/main/g/gconf/libgconf2-dev_3.2.6-4+b1_amd64.deb http://ftp.us.debian.org/debian/pool/main/g/glib2.0/libglib2.0-0_2.50.3-2_amd64.deb http://ftp.us.debian.org/debian/pool/main/g/glib2.0/libglib2.0-dev_2.50.3-2_amd64.deb +http://ftp.us.debian.org/debian/pool/main/g/gmp/libgmp10_6.1.2+dfsg-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/g/graphite2/libgraphite2-3_1.3.10-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/g/graphite2/libgraphite2-dev_1.3.10-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/g/gtk+2.0/libgtk2.0-0_2.24.31-2_amd64.deb @@ -62,6 +61,9 @@ http://ftp.us.debian.org/debian/pool/main/h/harfbuzz/libharfbuzz-dev_1.4.2-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/h/harfbuzz/libharfbuzz-gobject0_1.4.2-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/h/harfbuzz/libharfbuzz-icu0_1.4.2-1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/i/icu/libicu57_57.1-6+deb9u1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/j/jbigkit/libjbig0_2.1-3.1+b2_amd64.deb +http://ftp.us.debian.org/debian/pool/main/j/json-glib/libjson-glib-1.0-0_1.2.6-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/k/keyutils/libkeyutils1_1.5.9-9_amd64.deb http://ftp.us.debian.org/debian/pool/main/k/krb5/krb5-multidev_1.15-1+deb9u1_amd64.deb http://ftp.us.debian.org/debian/pool/main/k/krb5/libgssapi-krb5-2_1.15-1+deb9u1_amd64.deb @@ -73,9 +75,12 @@ http://ftp.us.debian.org/debian/pool/main/k/krb5/libkrb5-3_1.15-1+deb9u1_amd64.deb http://ftp.us.debian.org/debian/pool/main/k/krb5/libkrb5-dev_1.15-1+deb9u1_amd64.deb http://ftp.us.debian.org/debian/pool/main/k/krb5/libkrb5support0_1.15-1+deb9u1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/liba/libasyncns/libasyncns0_0.8-6_amd64.deb http://ftp.us.debian.org/debian/pool/main/libb/libbsd/libbsd0_0.8.3-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/libc/libcap2/libcap2_2.25-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/libc/libcap2/libcap-dev_2.25-1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/libc/libcap-ng/libcap-ng0_0.7.7-3+b1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/libd/libdatrie/libdatrie1_0.2.10-4+b1_amd64.deb http://ftp.us.debian.org/debian/pool/main/libd/libdrm/libdrm2_2.4.74-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/libd/libdrm/libdrm-amdgpu1_2.4.74-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/libd/libdrm/libdrm-dev_2.4.74-1_amd64.deb @@ -90,15 +95,26 @@ http://ftp.us.debian.org/debian/pool/main/libg/libgnome-keyring/libgnome-keyring-dev_3.12.0-1+b2_amd64.deb http://ftp.us.debian.org/debian/pool/main/libg/libgpg-error/libgpg-error0_1.26-2_amd64.deb http://ftp.us.debian.org/debian/pool/main/libg/libgpg-error/libgpg-error-dev_1.26-2_amd64.deb +http://ftp.us.debian.org/debian/pool/main/libi/libice/libice6_1.0.9-2_amd64.deb +http://ftp.us.debian.org/debian/pool/main/libi/libidl/libidl-2-0_0.8.14-4_amd64.deb +http://ftp.us.debian.org/debian/pool/main/libi/libidn/libidn11_1.33-1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/libj/libjpeg-turbo/libjpeg62-turbo_1.5.1-2_amd64.deb http://ftp.us.debian.org/debian/pool/main/libj/libjsoncpp/libjsoncpp1_1.7.4-3_amd64.deb http://ftp.us.debian.org/debian/pool/main/libj/libjsoncpp/libjsoncpp-dev_1.7.4-3_amd64.deb http://ftp.us.debian.org/debian/pool/main/libn/libnss-db/libnss-db_2.2.3pre1-6+b1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/libo/libogg/libogg0_1.3.2-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/libp/libp11/libp11-2_0.4.3-1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/libp/libpciaccess/libpciaccess0_0.13.4-1+b2_amd64.deb http://ftp.us.debian.org/debian/pool/main/libp/libpng1.6/libpng16-16_1.6.28-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/libp/libpng1.6/libpng-dev_1.6.28-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/libp/libpthread-stubs/libpthread-stubs0-dev_0.3-4_amd64.deb +http://ftp.us.debian.org/debian/pool/main/libr/librest/librest-0.7-0_0.8.0-2_amd64.deb http://ftp.us.debian.org/debian/pool/main/libs/libselinux/libselinux1_2.6-3+b3_amd64.deb +http://ftp.us.debian.org/debian/pool/main/libs/libsm/libsm6_1.2.2-1+b3_amd64.deb +http://ftp.us.debian.org/debian/pool/main/libs/libsndfile/libsndfile1_1.0.27-3_amd64.deb http://ftp.us.debian.org/debian/pool/main/libt/libtasn1-6/libtasn1-6_4.10-1.1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/libt/libthai/libthai0_0.1.26-1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/libt/libtool/libltdl7_2.4.6-2_amd64.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva1_1.7.3-2_amd64.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-dev_1.7.3-2_amd64.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-drm1_1.7.3-2_amd64.deb @@ -107,6 +123,8 @@ http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-tpi1_1.7.3-2_amd64.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-wayland1_1.7.3-2_amd64.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-x11-1_1.7.3-2_amd64.deb +http://ftp.us.debian.org/debian/pool/main/libv/libvorbis/libvorbis0a_1.3.5-4_amd64.deb +http://ftp.us.debian.org/debian/pool/main/libv/libvorbis/libvorbisenc2_1.3.5-4_amd64.deb http://ftp.us.debian.org/debian/pool/main/libx/libx11/libx11-6_1.6.4-3_amd64.deb http://ftp.us.debian.org/debian/pool/main/libx/libx11/libx11-dev_1.6.4-3_amd64.deb http://ftp.us.debian.org/debian/pool/main/libx/libx11/libx11-xcb1_1.6.4-3_amd64.deb @@ -124,10 +142,9 @@ http://ftp.us.debian.org/debian/pool/main/libx/libxcb/libxcb-shm0_1.12-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcb/libxcb-shm0-dev_1.12-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcb/libxcb-sync1_1.12-1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/libx/libxcb/libxcb-xfixes0_1.12-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcomposite/libxcomposite1_0.4.4-2_amd64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcomposite/libxcomposite-dev_0.4.4-2_amd64.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxcursor/libxcursor1_1.1.14-1+b4_amd64.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxcursor/libxcursor-dev_1.1.14-1+b4_amd64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxdamage/libxdamage1_1.1.4-2+b3_amd64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxdamage/libxdamage-dev_1.1.4-2+b3_amd64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxdmcp/libxdmcp6_1.1.2-3_amd64.deb @@ -140,8 +157,8 @@ http://ftp.us.debian.org/debian/pool/main/libx/libxi/libxi-dev_1.7.9-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxinerama/libxinerama1_1.1.3-1+b3_amd64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxinerama/libxinerama-dev_1.1.3-1+b3_amd64.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon0_0.7.1-1_amd64.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon-dev_0.7.1-1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon0_0.7.1-2~deb9u1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon-dev_0.7.1-2~deb9u1_amd64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxrandr/libxrandr2_1.5.1-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxrandr/libxrandr-dev_1.5.1-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxrender/libxrender1_0.9.10-1_amd64.deb @@ -154,6 +171,9 @@ http://ftp.us.debian.org/debian/pool/main/libx/libxtst/libxtst6_1.2.3-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxtst/libxtst-dev_1.2.3-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxxf86vm/libxxf86vm1_1.1.4-1+b2_amd64.deb +http://ftp.us.debian.org/debian/pool/main/l/lcms2/liblcms2-2_2.8-4_amd64.deb +http://ftp.us.debian.org/debian/pool/main/l/lz4/liblz4-1_0.0~r131-2+b1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/l/lzo2/liblzo2-2_2.08-1.2+b2_amd64.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/libegl1-mesa_13.0.6-1+b2_amd64.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/libegl1-mesa-dev_13.0.6-1+b2_amd64.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/libgbm1_13.0.6-1+b2_amd64.deb @@ -163,8 +183,11 @@ http://ftp.us.debian.org/debian/pool/main/m/mesa/libglapi-mesa_13.0.6-1+b2_amd64.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/libwayland-egl1-mesa_13.0.6-1+b2_amd64.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/mesa-common-dev_13.0.6-1+b2_amd64.deb +http://ftp.us.debian.org/debian/pool/main/n/nettle/libhogweed4_3.3-1+b2_amd64.deb +http://ftp.us.debian.org/debian/pool/main/n/nettle/libnettle6_3.3-1+b2_amd64.deb http://ftp.us.debian.org/debian/pool/main/n/nspr/libnspr4_4.12-6_amd64.deb http://ftp.us.debian.org/debian/pool/main/n/nspr/libnspr4-dev_4.12-6_amd64.deb +http://ftp.us.debian.org/debian/pool/main/o/orbit2/liborbit-2-0_2.14.19-2+b1_amd64.deb http://ftp.us.debian.org/debian/pool/main/o/orbit2/liborbit2_2.14.19-2+b1_amd64.deb http://ftp.us.debian.org/debian/pool/main/p/p11-kit/libp11-kit0_0.23.3-2_amd64.deb http://ftp.us.debian.org/debian/pool/main/p/pam/libpam0g_1.1.8-3.6_amd64.deb @@ -190,8 +213,15 @@ http://ftp.us.debian.org/debian/pool/main/s/speech-dispatcher/libspeechd2_0.8.6-4+deb9u1_amd64.deb http://ftp.us.debian.org/debian/pool/main/s/speech-dispatcher/libspeechd-dev_0.8.6-4+deb9u1_amd64.deb http://ftp.us.debian.org/debian/pool/main/s/speech-dispatcher/speech-dispatcher_0.8.6-4+deb9u1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/s/sqlite3/libsqlite3-0_3.16.2-5+deb9u1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/s/systemd/libsystemd0_232-25+deb9u1_amd64.deb http://ftp.us.debian.org/debian/pool/main/s/systemd/libudev1_232-25+deb9u1_amd64.deb http://ftp.us.debian.org/debian/pool/main/s/systemd/libudev-dev_232-25+deb9u1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/t/tcp-wrappers/libwrap0_7.6.q-26_amd64.deb +http://ftp.us.debian.org/debian/pool/main/u/unbound/libunbound2_1.6.0-3+deb9u1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/u/util-linux/libblkid1_2.29.2-1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/u/util-linux/libmount1_2.29.2-1_amd64.deb +http://ftp.us.debian.org/debian/pool/main/u/util-linux/libuuid1_2.29.2-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/w/wayland/libwayland-client0_1.12.0-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/w/wayland/libwayland-cursor0_1.12.0-1_amd64.deb http://ftp.us.debian.org/debian/pool/main/w/wayland/libwayland-dev_1.12.0-1_amd64.deb @@ -209,6 +239,8 @@ http://ftp.us.debian.org/debian/pool/main/x/x11proto-scrnsaver/x11proto-scrnsaver-dev_1.2.2-1_all.deb http://ftp.us.debian.org/debian/pool/main/x/x11proto-xext/x11proto-xext-dev_7.3.0-1_all.deb http://ftp.us.debian.org/debian/pool/main/x/x11proto-xinerama/x11proto-xinerama-dev_1.2.1-2_all.deb +http://ftp.us.debian.org/debian/pool/main/x/xft/libxft2_2.3.2-1+b2_amd64.deb +http://ftp.us.debian.org/debian/pool/main/x/xz-utils/liblzma5_5.2.2-1.2+b1_amd64.deb http://ftp.us.debian.org/debian/pool/main/z/zlib/zlib1g_1.2.8.dfsg-5_amd64.deb http://ftp.us.debian.org/debian/pool/main/z/zlib/zlib1g-dev_1.2.8.dfsg-5_amd64.deb http://security.debian.org/pool/updates/main/b/bluez/libbluetooth3_5.43-2+deb9u1_amd64.deb @@ -226,9 +258,15 @@ http://security.debian.org/pool/updates/main/g/gnutls28/libgnutlsxx28_3.5.8-5+deb9u1_amd64.deb http://security.debian.org/pool/updates/main/libg/libgcrypt20/libgcrypt20_1.7.6-2+deb9u2_amd64.deb http://security.debian.org/pool/updates/main/libg/libgcrypt20/libgcrypt20-dev_1.7.6-2+deb9u2_amd64.deb +http://security.debian.org/pool/updates/main/libs/libsoup2.4/libsoup2.4-1_2.56.0-2+deb9u1_amd64.deb +http://security.debian.org/pool/updates/main/libs/libsoup2.4/libsoup-gnome2.4-1_2.56.0-2+deb9u1_amd64.deb +http://security.debian.org/pool/updates/main/libx/libxcursor/libxcursor1_1.1.14-1+deb9u1_amd64.deb +http://security.debian.org/pool/updates/main/libx/libxcursor/libxcursor-dev_1.1.14-1+deb9u1_amd64.deb +http://security.debian.org/pool/updates/main/libx/libxml2/libxml2_2.9.4+dfsg1-2.2+deb9u1_amd64.deb http://security.debian.org/pool/updates/main/l/linux/linux-libc-dev_4.9.30-2+deb9u5_amd64.deb http://security.debian.org/pool/updates/main/n/nss/libnss3_3.26.2-1.1+deb9u1_amd64.deb http://security.debian.org/pool/updates/main/n/nss/libnss3-dev_3.26.2-1.1+deb9u1_amd64.deb http://security.debian.org/pool/updates/main/o/openssl1.0/libssl1.0.2_1.0.2l-2+deb9u1_amd64.deb http://security.debian.org/pool/updates/main/o/openssl/libssl1.1_1.1.0f-3+deb9u1_amd64.deb http://security.debian.org/pool/updates/main/o/openssl/libssl-dev_1.1.0f-3+deb9u1_amd64.deb +http://security.debian.org/pool/updates/main/t/tiff/libtiff5_4.0.8-2+deb9u1_amd64.deb
diff --git a/build/linux/sysroot_scripts/packagelist.stretch.arm b/build/linux/sysroot_scripts/packagelist.stretch.arm index 3de9a8ef..2a9c6eb 100644 --- a/build/linux/sysroot_scripts/packagelist.stretch.arm +++ b/build/linux/sysroot_scripts/packagelist.stretch.arm
@@ -16,19 +16,20 @@ http://ftp.us.debian.org/debian/pool/main/c/cairo/libcairo2-dev_1.14.8-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/c/cairo/libcairo-gobject2_1.14.8-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/c/cairo/libcairo-script-interpreter2_1.14.8-1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/c/colord/libcolord2_1.3.3-2_armhf.deb http://ftp.us.debian.org/debian/pool/main/c/cups/libcups2_2.2.1-8_armhf.deb http://ftp.us.debian.org/debian/pool/main/c/cups/libcups2-dev_2.2.1-8_armhf.deb http://ftp.us.debian.org/debian/pool/main/c/cups/libcupsimage2_2.2.1-8_armhf.deb http://ftp.us.debian.org/debian/pool/main/c/cups/libcupsimage2-dev_2.2.1-8_armhf.deb +http://ftp.us.debian.org/debian/pool/main/d/db5.3/libdb5.3_5.3.28-12+deb9u1_armhf.deb http://ftp.us.debian.org/debian/pool/main/d/dbus-glib/libdbus-glib-1-2_0.108-2_armhf.deb -http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-3_1.10.22-0+deb9u1_armhf.deb -http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-dev_1.10.22-0+deb9u1_armhf.deb -http://ftp.us.debian.org/debian/pool/main/d/d-conf/libdconf1_0.26.0-2+b1_armhf.deb -http://ftp.us.debian.org/debian/pool/main/d/d-conf/libdconf-dev_0.26.0-2+b1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-3_1.10.24-0+deb9u1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-dev_1.10.24-0+deb9u1_armhf.deb http://ftp.us.debian.org/debian/pool/main/e/e2fsprogs/comerr-dev_2.1-1.43.4-2_armhf.deb http://ftp.us.debian.org/debian/pool/main/e/e2fsprogs/libcomerr2_1.43.4-2_armhf.deb http://ftp.us.debian.org/debian/pool/main/e/elfutils/libelf1_0.168-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/e/elfutils/libelf-dev_0.168-1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/f/flac/libflac8_1.3.2-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/f/fontconfig/libfontconfig1_2.11.0-6.7+b1_armhf.deb http://ftp.us.debian.org/debian/pool/main/f/fontconfig/libfontconfig1-dev_2.11.0-6.7+b1_armhf.deb http://ftp.us.debian.org/debian/pool/main/f/freetype/libfreetype6_2.6.3-3.2_armhf.deb @@ -41,11 +42,9 @@ http://ftp.us.debian.org/debian/pool/main/g/gcc-6/libstdc++6_6.3.0-18_armhf.deb http://ftp.us.debian.org/debian/pool/main/g/gcc-6/libstdc++-6-dev_6.3.0-18_armhf.deb http://ftp.us.debian.org/debian/pool/main/g/gcc-6/libubsan0_6.3.0-18_armhf.deb -http://ftp.us.debian.org/debian/pool/main/g/gconf/libgconf2-4_3.2.6-4+b1_armhf.deb -http://ftp.us.debian.org/debian/pool/main/g/gconf/libgconf-2-4_3.2.6-4+b1_armhf.deb -http://ftp.us.debian.org/debian/pool/main/g/gconf/libgconf2-dev_3.2.6-4+b1_armhf.deb http://ftp.us.debian.org/debian/pool/main/g/glib2.0/libglib2.0-0_2.50.3-2_armhf.deb http://ftp.us.debian.org/debian/pool/main/g/glib2.0/libglib2.0-dev_2.50.3-2_armhf.deb +http://ftp.us.debian.org/debian/pool/main/g/gmp/libgmp10_6.1.2+dfsg-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/g/graphite2/libgraphite2-3_1.3.10-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/g/graphite2/libgraphite2-dev_1.3.10-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/g/gtk+2.0/libgtk2.0-0_2.24.31-2_armhf.deb @@ -56,6 +55,9 @@ http://ftp.us.debian.org/debian/pool/main/h/harfbuzz/libharfbuzz-dev_1.4.2-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/h/harfbuzz/libharfbuzz-gobject0_1.4.2-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/h/harfbuzz/libharfbuzz-icu0_1.4.2-1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/i/icu/libicu57_57.1-6+deb9u1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/j/jbigkit/libjbig0_2.1-3.1+b2_armhf.deb +http://ftp.us.debian.org/debian/pool/main/j/json-glib/libjson-glib-1.0-0_1.2.6-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/k/keyutils/libkeyutils1_1.5.9-9_armhf.deb http://ftp.us.debian.org/debian/pool/main/k/krb5/krb5-multidev_1.15-1+deb9u1_armhf.deb http://ftp.us.debian.org/debian/pool/main/k/krb5/libgssapi-krb5-2_1.15-1+deb9u1_armhf.deb @@ -67,9 +69,12 @@ http://ftp.us.debian.org/debian/pool/main/k/krb5/libkrb5-3_1.15-1+deb9u1_armhf.deb http://ftp.us.debian.org/debian/pool/main/k/krb5/libkrb5-dev_1.15-1+deb9u1_armhf.deb http://ftp.us.debian.org/debian/pool/main/k/krb5/libkrb5support0_1.15-1+deb9u1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/liba/libasyncns/libasyncns0_0.8-6_armhf.deb http://ftp.us.debian.org/debian/pool/main/libb/libbsd/libbsd0_0.8.3-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/libc/libcap2/libcap2_2.25-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/libc/libcap2/libcap-dev_2.25-1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/libc/libcap-ng/libcap-ng0_0.7.7-3+b1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/libd/libdatrie/libdatrie1_0.2.10-4+b1_armhf.deb http://ftp.us.debian.org/debian/pool/main/libd/libdrm/libdrm2_2.4.74-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/libd/libdrm/libdrm-amdgpu1_2.4.74-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/libd/libdrm/libdrm-dev_2.4.74-1_armhf.deb @@ -87,15 +92,26 @@ http://ftp.us.debian.org/debian/pool/main/libg/libgnome-keyring/libgnome-keyring-dev_3.12.0-1+b2_armhf.deb http://ftp.us.debian.org/debian/pool/main/libg/libgpg-error/libgpg-error0_1.26-2_armhf.deb http://ftp.us.debian.org/debian/pool/main/libg/libgpg-error/libgpg-error-dev_1.26-2_armhf.deb +http://ftp.us.debian.org/debian/pool/main/libi/libice/libice6_1.0.9-2_armhf.deb +http://ftp.us.debian.org/debian/pool/main/libi/libidl/libidl-2-0_0.8.14-4_armhf.deb +http://ftp.us.debian.org/debian/pool/main/libi/libidn/libidn11_1.33-1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/libj/libjpeg-turbo/libjpeg62-turbo_1.5.1-2_armhf.deb http://ftp.us.debian.org/debian/pool/main/libj/libjsoncpp/libjsoncpp1_1.7.4-3_armhf.deb http://ftp.us.debian.org/debian/pool/main/libj/libjsoncpp/libjsoncpp-dev_1.7.4-3_armhf.deb http://ftp.us.debian.org/debian/pool/main/libn/libnss-db/libnss-db_2.2.3pre1-6+b1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/libo/libogg/libogg0_1.3.2-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/libp/libp11/libp11-2_0.4.3-1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/libp/libpciaccess/libpciaccess0_0.13.4-1+b2_armhf.deb http://ftp.us.debian.org/debian/pool/main/libp/libpng1.6/libpng16-16_1.6.28-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/libp/libpng1.6/libpng-dev_1.6.28-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/libp/libpthread-stubs/libpthread-stubs0-dev_0.3-4_armhf.deb +http://ftp.us.debian.org/debian/pool/main/libr/librest/librest-0.7-0_0.8.0-2_armhf.deb http://ftp.us.debian.org/debian/pool/main/libs/libselinux/libselinux1_2.6-3+b3_armhf.deb +http://ftp.us.debian.org/debian/pool/main/libs/libsm/libsm6_1.2.2-1+b3_armhf.deb +http://ftp.us.debian.org/debian/pool/main/libs/libsndfile/libsndfile1_1.0.27-3_armhf.deb http://ftp.us.debian.org/debian/pool/main/libt/libtasn1-6/libtasn1-6_4.10-1.1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/libt/libthai/libthai0_0.1.26-1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/libt/libtool/libltdl7_2.4.6-2_armhf.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva1_1.7.3-2_armhf.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-dev_1.7.3-2_armhf.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-drm1_1.7.3-2_armhf.deb @@ -104,6 +120,8 @@ http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-tpi1_1.7.3-2_armhf.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-wayland1_1.7.3-2_armhf.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-x11-1_1.7.3-2_armhf.deb +http://ftp.us.debian.org/debian/pool/main/libv/libvorbis/libvorbis0a_1.3.5-4_armhf.deb +http://ftp.us.debian.org/debian/pool/main/libv/libvorbis/libvorbisenc2_1.3.5-4_armhf.deb http://ftp.us.debian.org/debian/pool/main/libx/libx11/libx11-6_1.6.4-3_armhf.deb http://ftp.us.debian.org/debian/pool/main/libx/libx11/libx11-dev_1.6.4-3_armhf.deb http://ftp.us.debian.org/debian/pool/main/libx/libx11/libx11-xcb1_1.6.4-3_armhf.deb @@ -121,10 +139,9 @@ http://ftp.us.debian.org/debian/pool/main/libx/libxcb/libxcb-shm0_1.12-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcb/libxcb-shm0-dev_1.12-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcb/libxcb-sync1_1.12-1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/libx/libxcb/libxcb-xfixes0_1.12-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcomposite/libxcomposite1_0.4.4-2_armhf.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcomposite/libxcomposite-dev_0.4.4-2_armhf.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxcursor/libxcursor1_1.1.14-1+b4_armhf.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxcursor/libxcursor-dev_1.1.14-1+b4_armhf.deb http://ftp.us.debian.org/debian/pool/main/libx/libxdamage/libxdamage1_1.1.4-2+b3_armhf.deb http://ftp.us.debian.org/debian/pool/main/libx/libxdamage/libxdamage-dev_1.1.4-2+b3_armhf.deb http://ftp.us.debian.org/debian/pool/main/libx/libxdmcp/libxdmcp6_1.1.2-3_armhf.deb @@ -137,8 +154,8 @@ http://ftp.us.debian.org/debian/pool/main/libx/libxi/libxi-dev_1.7.9-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/libx/libxinerama/libxinerama1_1.1.3-1+b3_armhf.deb http://ftp.us.debian.org/debian/pool/main/libx/libxinerama/libxinerama-dev_1.1.3-1+b3_armhf.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon0_0.7.1-1_armhf.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon-dev_0.7.1-1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon0_0.7.1-2~deb9u1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon-dev_0.7.1-2~deb9u1_armhf.deb http://ftp.us.debian.org/debian/pool/main/libx/libxrandr/libxrandr2_1.5.1-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/libx/libxrandr/libxrandr-dev_1.5.1-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/libx/libxrender/libxrender1_0.9.10-1_armhf.deb @@ -151,6 +168,9 @@ http://ftp.us.debian.org/debian/pool/main/libx/libxtst/libxtst6_1.2.3-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/libx/libxtst/libxtst-dev_1.2.3-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/libx/libxxf86vm/libxxf86vm1_1.1.4-1+b2_armhf.deb +http://ftp.us.debian.org/debian/pool/main/l/lcms2/liblcms2-2_2.8-4_armhf.deb +http://ftp.us.debian.org/debian/pool/main/l/lz4/liblz4-1_0.0~r131-2+b1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/l/lzo2/liblzo2-2_2.08-1.2+b2_armhf.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/libegl1-mesa_13.0.6-1+b2_armhf.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/libegl1-mesa-dev_13.0.6-1+b2_armhf.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/libgbm1_13.0.6-1+b2_armhf.deb @@ -160,8 +180,11 @@ http://ftp.us.debian.org/debian/pool/main/m/mesa/libglapi-mesa_13.0.6-1+b2_armhf.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/libwayland-egl1-mesa_13.0.6-1+b2_armhf.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/mesa-common-dev_13.0.6-1+b2_armhf.deb +http://ftp.us.debian.org/debian/pool/main/n/nettle/libhogweed4_3.3-1+b2_armhf.deb +http://ftp.us.debian.org/debian/pool/main/n/nettle/libnettle6_3.3-1+b2_armhf.deb http://ftp.us.debian.org/debian/pool/main/n/nspr/libnspr4_4.12-6_armhf.deb http://ftp.us.debian.org/debian/pool/main/n/nspr/libnspr4-dev_4.12-6_armhf.deb +http://ftp.us.debian.org/debian/pool/main/o/orbit2/liborbit-2-0_2.14.19-2+b1_armhf.deb http://ftp.us.debian.org/debian/pool/main/o/orbit2/liborbit2_2.14.19-2+b1_armhf.deb http://ftp.us.debian.org/debian/pool/main/p/p11-kit/libp11-kit0_0.23.3-2_armhf.deb http://ftp.us.debian.org/debian/pool/main/p/pam/libpam0g_1.1.8-3.6_armhf.deb @@ -187,8 +210,15 @@ http://ftp.us.debian.org/debian/pool/main/s/speech-dispatcher/libspeechd2_0.8.6-4+deb9u1_armhf.deb http://ftp.us.debian.org/debian/pool/main/s/speech-dispatcher/libspeechd-dev_0.8.6-4+deb9u1_armhf.deb http://ftp.us.debian.org/debian/pool/main/s/speech-dispatcher/speech-dispatcher_0.8.6-4+deb9u1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/s/sqlite3/libsqlite3-0_3.16.2-5+deb9u1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/s/systemd/libsystemd0_232-25+deb9u1_armhf.deb http://ftp.us.debian.org/debian/pool/main/s/systemd/libudev1_232-25+deb9u1_armhf.deb http://ftp.us.debian.org/debian/pool/main/s/systemd/libudev-dev_232-25+deb9u1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/t/tcp-wrappers/libwrap0_7.6.q-26_armhf.deb +http://ftp.us.debian.org/debian/pool/main/u/unbound/libunbound2_1.6.0-3+deb9u1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/u/util-linux/libblkid1_2.29.2-1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/u/util-linux/libmount1_2.29.2-1_armhf.deb +http://ftp.us.debian.org/debian/pool/main/u/util-linux/libuuid1_2.29.2-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/w/wayland/libwayland-client0_1.12.0-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/w/wayland/libwayland-cursor0_1.12.0-1_armhf.deb http://ftp.us.debian.org/debian/pool/main/w/wayland/libwayland-dev_1.12.0-1_armhf.deb @@ -206,6 +236,8 @@ http://ftp.us.debian.org/debian/pool/main/x/x11proto-scrnsaver/x11proto-scrnsaver-dev_1.2.2-1_all.deb http://ftp.us.debian.org/debian/pool/main/x/x11proto-xext/x11proto-xext-dev_7.3.0-1_all.deb http://ftp.us.debian.org/debian/pool/main/x/x11proto-xinerama/x11proto-xinerama-dev_1.2.1-2_all.deb +http://ftp.us.debian.org/debian/pool/main/x/xft/libxft2_2.3.2-1+b2_armhf.deb +http://ftp.us.debian.org/debian/pool/main/x/xz-utils/liblzma5_5.2.2-1.2+b1_armhf.deb http://ftp.us.debian.org/debian/pool/main/z/zlib/zlib1g_1.2.8.dfsg-5_armhf.deb http://ftp.us.debian.org/debian/pool/main/z/zlib/zlib1g-dev_1.2.8.dfsg-5_armhf.deb http://security.debian.org/pool/updates/main/b/bluez/libbluetooth3_5.43-2+deb9u1_armhf.deb @@ -223,9 +255,15 @@ http://security.debian.org/pool/updates/main/g/gnutls28/libgnutlsxx28_3.5.8-5+deb9u1_armhf.deb http://security.debian.org/pool/updates/main/libg/libgcrypt20/libgcrypt20_1.7.6-2+deb9u2_armhf.deb http://security.debian.org/pool/updates/main/libg/libgcrypt20/libgcrypt20-dev_1.7.6-2+deb9u2_armhf.deb +http://security.debian.org/pool/updates/main/libs/libsoup2.4/libsoup2.4-1_2.56.0-2+deb9u1_armhf.deb +http://security.debian.org/pool/updates/main/libs/libsoup2.4/libsoup-gnome2.4-1_2.56.0-2+deb9u1_armhf.deb +http://security.debian.org/pool/updates/main/libx/libxcursor/libxcursor1_1.1.14-1+deb9u1_armhf.deb +http://security.debian.org/pool/updates/main/libx/libxcursor/libxcursor-dev_1.1.14-1+deb9u1_armhf.deb +http://security.debian.org/pool/updates/main/libx/libxml2/libxml2_2.9.4+dfsg1-2.2+deb9u1_armhf.deb http://security.debian.org/pool/updates/main/l/linux/linux-libc-dev_4.9.30-2+deb9u5_armhf.deb http://security.debian.org/pool/updates/main/n/nss/libnss3_3.26.2-1.1+deb9u1_armhf.deb http://security.debian.org/pool/updates/main/n/nss/libnss3-dev_3.26.2-1.1+deb9u1_armhf.deb http://security.debian.org/pool/updates/main/o/openssl1.0/libssl1.0.2_1.0.2l-2+deb9u1_armhf.deb http://security.debian.org/pool/updates/main/o/openssl/libssl1.1_1.1.0f-3+deb9u1_armhf.deb http://security.debian.org/pool/updates/main/o/openssl/libssl-dev_1.1.0f-3+deb9u1_armhf.deb +http://security.debian.org/pool/updates/main/t/tiff/libtiff5_4.0.8-2+deb9u1_armhf.deb
diff --git a/build/linux/sysroot_scripts/packagelist.stretch.arm64 b/build/linux/sysroot_scripts/packagelist.stretch.arm64 index d3985f67..51bd50b 100644 --- a/build/linux/sysroot_scripts/packagelist.stretch.arm64 +++ b/build/linux/sysroot_scripts/packagelist.stretch.arm64
@@ -23,10 +23,8 @@ http://ftp.us.debian.org/debian/pool/main/c/cups/libcupsimage2-dev_2.2.1-8_arm64.deb http://ftp.us.debian.org/debian/pool/main/d/db5.3/libdb5.3_5.3.28-12+deb9u1_arm64.deb http://ftp.us.debian.org/debian/pool/main/d/dbus-glib/libdbus-glib-1-2_0.108-2_arm64.deb -http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-3_1.10.22-0+deb9u1_arm64.deb -http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-dev_1.10.22-0+deb9u1_arm64.deb -http://ftp.us.debian.org/debian/pool/main/d/d-conf/libdconf1_0.26.0-2+b1_arm64.deb -http://ftp.us.debian.org/debian/pool/main/d/d-conf/libdconf-dev_0.26.0-2+b1_arm64.deb +http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-3_1.10.24-0+deb9u1_arm64.deb +http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-dev_1.10.24-0+deb9u1_arm64.deb http://ftp.us.debian.org/debian/pool/main/e/e2fsprogs/comerr-dev_2.1-1.43.4-2_arm64.deb http://ftp.us.debian.org/debian/pool/main/e/e2fsprogs/libcomerr2_1.43.4-2_arm64.deb http://ftp.us.debian.org/debian/pool/main/e/elfutils/libelf1_0.168-1_arm64.deb @@ -45,9 +43,6 @@ http://ftp.us.debian.org/debian/pool/main/g/gcc-6/libstdc++6_6.3.0-18_arm64.deb http://ftp.us.debian.org/debian/pool/main/g/gcc-6/libstdc++-6-dev_6.3.0-18_arm64.deb http://ftp.us.debian.org/debian/pool/main/g/gcc-6/libubsan0_6.3.0-18_arm64.deb -http://ftp.us.debian.org/debian/pool/main/g/gconf/libgconf2-4_3.2.6-4+b1_arm64.deb -http://ftp.us.debian.org/debian/pool/main/g/gconf/libgconf-2-4_3.2.6-4+b1_arm64.deb -http://ftp.us.debian.org/debian/pool/main/g/gconf/libgconf2-dev_3.2.6-4+b1_arm64.deb http://ftp.us.debian.org/debian/pool/main/g/glib2.0/libglib2.0-0_2.50.3-2_arm64.deb http://ftp.us.debian.org/debian/pool/main/g/glib2.0/libglib2.0-dev_2.50.3-2_arm64.deb http://ftp.us.debian.org/debian/pool/main/g/gmp/libgmp10_6.1.2+dfsg-1_arm64.deb @@ -62,7 +57,7 @@ http://ftp.us.debian.org/debian/pool/main/h/harfbuzz/libharfbuzz-dev_1.4.2-1_arm64.deb http://ftp.us.debian.org/debian/pool/main/h/harfbuzz/libharfbuzz-gobject0_1.4.2-1_arm64.deb http://ftp.us.debian.org/debian/pool/main/h/harfbuzz/libharfbuzz-icu0_1.4.2-1_arm64.deb -http://ftp.us.debian.org/debian/pool/main/i/icu/libicu57_57.1-6_arm64.deb +http://ftp.us.debian.org/debian/pool/main/i/icu/libicu57_57.1-6+deb9u1_arm64.deb http://ftp.us.debian.org/debian/pool/main/j/jbigkit/libjbig0_2.1-3.1+b2_arm64.deb http://ftp.us.debian.org/debian/pool/main/j/json-glib/libjson-glib-1.0-0_1.2.6-1_arm64.deb http://ftp.us.debian.org/debian/pool/main/k/keyutils/libkeyutils1_1.5.9-9_arm64.deb @@ -148,8 +143,6 @@ http://ftp.us.debian.org/debian/pool/main/libx/libxcb/libxcb-xfixes0_1.12-1_arm64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcomposite/libxcomposite1_0.4.4-2_arm64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcomposite/libxcomposite-dev_0.4.4-2_arm64.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxcursor/libxcursor1_1.1.14-1+b4_arm64.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxcursor/libxcursor-dev_1.1.14-1+b4_arm64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxdamage/libxdamage1_1.1.4-2+b3_arm64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxdamage/libxdamage-dev_1.1.4-2+b3_arm64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxdmcp/libxdmcp6_1.1.2-3_arm64.deb @@ -162,8 +155,8 @@ http://ftp.us.debian.org/debian/pool/main/libx/libxi/libxi-dev_1.7.9-1_arm64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxinerama/libxinerama1_1.1.3-1+b3_arm64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxinerama/libxinerama-dev_1.1.3-1+b3_arm64.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon0_0.7.1-1_arm64.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon-dev_0.7.1-1_arm64.deb +http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon0_0.7.1-2~deb9u1_arm64.deb +http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon-dev_0.7.1-2~deb9u1_arm64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxrandr/libxrandr2_1.5.1-1_arm64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxrandr/libxrandr-dev_1.5.1-1_arm64.deb http://ftp.us.debian.org/debian/pool/main/libx/libxrender/libxrender1_0.9.10-1_arm64.deb @@ -218,7 +211,7 @@ http://ftp.us.debian.org/debian/pool/main/s/speech-dispatcher/libspeechd2_0.8.6-4+deb9u1_arm64.deb http://ftp.us.debian.org/debian/pool/main/s/speech-dispatcher/libspeechd-dev_0.8.6-4+deb9u1_arm64.deb http://ftp.us.debian.org/debian/pool/main/s/speech-dispatcher/speech-dispatcher_0.8.6-4+deb9u1_arm64.deb -http://ftp.us.debian.org/debian/pool/main/s/sqlite3/libsqlite3-0_3.16.2-5_arm64.deb +http://ftp.us.debian.org/debian/pool/main/s/sqlite3/libsqlite3-0_3.16.2-5+deb9u1_arm64.deb http://ftp.us.debian.org/debian/pool/main/s/systemd/libsystemd0_232-25+deb9u1_arm64.deb http://ftp.us.debian.org/debian/pool/main/s/systemd/libudev1_232-25+deb9u1_arm64.deb http://ftp.us.debian.org/debian/pool/main/s/systemd/libudev-dev_232-25+deb9u1_arm64.deb @@ -265,6 +258,8 @@ http://security.debian.org/pool/updates/main/libg/libgcrypt20/libgcrypt20-dev_1.7.6-2+deb9u2_arm64.deb http://security.debian.org/pool/updates/main/libs/libsoup2.4/libsoup2.4-1_2.56.0-2+deb9u1_arm64.deb http://security.debian.org/pool/updates/main/libs/libsoup2.4/libsoup-gnome2.4-1_2.56.0-2+deb9u1_arm64.deb +http://security.debian.org/pool/updates/main/libx/libxcursor/libxcursor1_1.1.14-1+deb9u1_arm64.deb +http://security.debian.org/pool/updates/main/libx/libxcursor/libxcursor-dev_1.1.14-1+deb9u1_arm64.deb http://security.debian.org/pool/updates/main/libx/libxml2/libxml2_2.9.4+dfsg1-2.2+deb9u1_arm64.deb http://security.debian.org/pool/updates/main/l/linux/linux-libc-dev_4.9.30-2+deb9u5_arm64.deb http://security.debian.org/pool/updates/main/n/nss/libnss3_3.26.2-1.1+deb9u1_arm64.deb
diff --git a/build/linux/sysroot_scripts/packagelist.stretch.i386 b/build/linux/sysroot_scripts/packagelist.stretch.i386 index 28a2423..95afc5a2 100644 --- a/build/linux/sysroot_scripts/packagelist.stretch.i386 +++ b/build/linux/sysroot_scripts/packagelist.stretch.i386
@@ -16,19 +16,20 @@ http://ftp.us.debian.org/debian/pool/main/c/cairo/libcairo2-dev_1.14.8-1_i386.deb http://ftp.us.debian.org/debian/pool/main/c/cairo/libcairo-gobject2_1.14.8-1_i386.deb http://ftp.us.debian.org/debian/pool/main/c/cairo/libcairo-script-interpreter2_1.14.8-1_i386.deb +http://ftp.us.debian.org/debian/pool/main/c/colord/libcolord2_1.3.3-2_i386.deb http://ftp.us.debian.org/debian/pool/main/c/cups/libcups2_2.2.1-8_i386.deb http://ftp.us.debian.org/debian/pool/main/c/cups/libcups2-dev_2.2.1-8_i386.deb http://ftp.us.debian.org/debian/pool/main/c/cups/libcupsimage2_2.2.1-8_i386.deb http://ftp.us.debian.org/debian/pool/main/c/cups/libcupsimage2-dev_2.2.1-8_i386.deb +http://ftp.us.debian.org/debian/pool/main/d/db5.3/libdb5.3_5.3.28-12+deb9u1_i386.deb http://ftp.us.debian.org/debian/pool/main/d/dbus-glib/libdbus-glib-1-2_0.108-2_i386.deb -http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-3_1.10.22-0+deb9u1_i386.deb -http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-dev_1.10.22-0+deb9u1_i386.deb -http://ftp.us.debian.org/debian/pool/main/d/d-conf/libdconf1_0.26.0-2+b1_i386.deb -http://ftp.us.debian.org/debian/pool/main/d/d-conf/libdconf-dev_0.26.0-2+b1_i386.deb +http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-3_1.10.24-0+deb9u1_i386.deb +http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-dev_1.10.24-0+deb9u1_i386.deb http://ftp.us.debian.org/debian/pool/main/e/e2fsprogs/comerr-dev_2.1-1.43.4-2_i386.deb http://ftp.us.debian.org/debian/pool/main/e/e2fsprogs/libcomerr2_1.43.4-2_i386.deb http://ftp.us.debian.org/debian/pool/main/e/elfutils/libelf1_0.168-1_i386.deb http://ftp.us.debian.org/debian/pool/main/e/elfutils/libelf-dev_0.168-1_i386.deb +http://ftp.us.debian.org/debian/pool/main/f/flac/libflac8_1.3.2-1_i386.deb http://ftp.us.debian.org/debian/pool/main/f/fontconfig/libfontconfig1_2.11.0-6.7+b1_i386.deb http://ftp.us.debian.org/debian/pool/main/f/fontconfig/libfontconfig1-dev_2.11.0-6.7+b1_i386.deb http://ftp.us.debian.org/debian/pool/main/f/freetype/libfreetype6_2.6.3-3.2_i386.deb @@ -45,11 +46,9 @@ http://ftp.us.debian.org/debian/pool/main/g/gcc-6/libstdc++6_6.3.0-18_i386.deb http://ftp.us.debian.org/debian/pool/main/g/gcc-6/libstdc++-6-dev_6.3.0-18_i386.deb http://ftp.us.debian.org/debian/pool/main/g/gcc-6/libubsan0_6.3.0-18_i386.deb -http://ftp.us.debian.org/debian/pool/main/g/gconf/libgconf-2-4_3.2.6-4+b1_i386.deb -http://ftp.us.debian.org/debian/pool/main/g/gconf/libgconf2-4_3.2.6-4+b1_i386.deb -http://ftp.us.debian.org/debian/pool/main/g/gconf/libgconf2-dev_3.2.6-4+b1_i386.deb http://ftp.us.debian.org/debian/pool/main/g/glib2.0/libglib2.0-0_2.50.3-2_i386.deb http://ftp.us.debian.org/debian/pool/main/g/glib2.0/libglib2.0-dev_2.50.3-2_i386.deb +http://ftp.us.debian.org/debian/pool/main/g/gmp/libgmp10_6.1.2+dfsg-1_i386.deb http://ftp.us.debian.org/debian/pool/main/g/graphite2/libgraphite2-3_1.3.10-1_i386.deb http://ftp.us.debian.org/debian/pool/main/g/graphite2/libgraphite2-dev_1.3.10-1_i386.deb http://ftp.us.debian.org/debian/pool/main/g/gtk+2.0/libgtk2.0-0_2.24.31-2_i386.deb @@ -60,6 +59,9 @@ http://ftp.us.debian.org/debian/pool/main/h/harfbuzz/libharfbuzz-dev_1.4.2-1_i386.deb http://ftp.us.debian.org/debian/pool/main/h/harfbuzz/libharfbuzz-gobject0_1.4.2-1_i386.deb http://ftp.us.debian.org/debian/pool/main/h/harfbuzz/libharfbuzz-icu0_1.4.2-1_i386.deb +http://ftp.us.debian.org/debian/pool/main/i/icu/libicu57_57.1-6+deb9u1_i386.deb +http://ftp.us.debian.org/debian/pool/main/j/jbigkit/libjbig0_2.1-3.1+b2_i386.deb +http://ftp.us.debian.org/debian/pool/main/j/json-glib/libjson-glib-1.0-0_1.2.6-1_i386.deb http://ftp.us.debian.org/debian/pool/main/k/keyutils/libkeyutils1_1.5.9-9_i386.deb http://ftp.us.debian.org/debian/pool/main/k/krb5/krb5-multidev_1.15-1+deb9u1_i386.deb http://ftp.us.debian.org/debian/pool/main/k/krb5/libgssapi-krb5-2_1.15-1+deb9u1_i386.deb @@ -71,9 +73,12 @@ http://ftp.us.debian.org/debian/pool/main/k/krb5/libkrb5-3_1.15-1+deb9u1_i386.deb http://ftp.us.debian.org/debian/pool/main/k/krb5/libkrb5-dev_1.15-1+deb9u1_i386.deb http://ftp.us.debian.org/debian/pool/main/k/krb5/libkrb5support0_1.15-1+deb9u1_i386.deb +http://ftp.us.debian.org/debian/pool/main/liba/libasyncns/libasyncns0_0.8-6_i386.deb http://ftp.us.debian.org/debian/pool/main/libb/libbsd/libbsd0_0.8.3-1_i386.deb http://ftp.us.debian.org/debian/pool/main/libc/libcap2/libcap2_2.25-1_i386.deb http://ftp.us.debian.org/debian/pool/main/libc/libcap2/libcap-dev_2.25-1_i386.deb +http://ftp.us.debian.org/debian/pool/main/libc/libcap-ng/libcap-ng0_0.7.7-3+b1_i386.deb +http://ftp.us.debian.org/debian/pool/main/libd/libdatrie/libdatrie1_0.2.10-4+b1_i386.deb http://ftp.us.debian.org/debian/pool/main/libd/libdrm/libdrm2_2.4.74-1_i386.deb http://ftp.us.debian.org/debian/pool/main/libd/libdrm/libdrm-amdgpu1_2.4.74-1_i386.deb http://ftp.us.debian.org/debian/pool/main/libd/libdrm/libdrm-dev_2.4.74-1_i386.deb @@ -88,15 +93,26 @@ http://ftp.us.debian.org/debian/pool/main/libg/libgnome-keyring/libgnome-keyring-dev_3.12.0-1+b2_i386.deb http://ftp.us.debian.org/debian/pool/main/libg/libgpg-error/libgpg-error0_1.26-2_i386.deb http://ftp.us.debian.org/debian/pool/main/libg/libgpg-error/libgpg-error-dev_1.26-2_i386.deb +http://ftp.us.debian.org/debian/pool/main/libi/libice/libice6_1.0.9-2_i386.deb +http://ftp.us.debian.org/debian/pool/main/libi/libidl/libidl-2-0_0.8.14-4_i386.deb +http://ftp.us.debian.org/debian/pool/main/libi/libidn/libidn11_1.33-1_i386.deb +http://ftp.us.debian.org/debian/pool/main/libj/libjpeg-turbo/libjpeg62-turbo_1.5.1-2_i386.deb http://ftp.us.debian.org/debian/pool/main/libj/libjsoncpp/libjsoncpp1_1.7.4-3_i386.deb http://ftp.us.debian.org/debian/pool/main/libj/libjsoncpp/libjsoncpp-dev_1.7.4-3_i386.deb http://ftp.us.debian.org/debian/pool/main/libn/libnss-db/libnss-db_2.2.3pre1-6+b1_i386.deb +http://ftp.us.debian.org/debian/pool/main/libo/libogg/libogg0_1.3.2-1_i386.deb http://ftp.us.debian.org/debian/pool/main/libp/libp11/libp11-2_0.4.3-1_i386.deb +http://ftp.us.debian.org/debian/pool/main/libp/libpciaccess/libpciaccess0_0.13.4-1+b2_i386.deb http://ftp.us.debian.org/debian/pool/main/libp/libpng1.6/libpng16-16_1.6.28-1_i386.deb http://ftp.us.debian.org/debian/pool/main/libp/libpng1.6/libpng-dev_1.6.28-1_i386.deb http://ftp.us.debian.org/debian/pool/main/libp/libpthread-stubs/libpthread-stubs0-dev_0.3-4_i386.deb +http://ftp.us.debian.org/debian/pool/main/libr/librest/librest-0.7-0_0.8.0-2_i386.deb http://ftp.us.debian.org/debian/pool/main/libs/libselinux/libselinux1_2.6-3+b3_i386.deb +http://ftp.us.debian.org/debian/pool/main/libs/libsm/libsm6_1.2.2-1+b3_i386.deb +http://ftp.us.debian.org/debian/pool/main/libs/libsndfile/libsndfile1_1.0.27-3_i386.deb http://ftp.us.debian.org/debian/pool/main/libt/libtasn1-6/libtasn1-6_4.10-1.1_i386.deb +http://ftp.us.debian.org/debian/pool/main/libt/libthai/libthai0_0.1.26-1_i386.deb +http://ftp.us.debian.org/debian/pool/main/libt/libtool/libltdl7_2.4.6-2_i386.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva1_1.7.3-2_i386.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-dev_1.7.3-2_i386.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-drm1_1.7.3-2_i386.deb @@ -105,6 +121,8 @@ http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-tpi1_1.7.3-2_i386.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-wayland1_1.7.3-2_i386.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-x11-1_1.7.3-2_i386.deb +http://ftp.us.debian.org/debian/pool/main/libv/libvorbis/libvorbis0a_1.3.5-4_i386.deb +http://ftp.us.debian.org/debian/pool/main/libv/libvorbis/libvorbisenc2_1.3.5-4_i386.deb http://ftp.us.debian.org/debian/pool/main/libx/libx11/libx11-6_1.6.4-3_i386.deb http://ftp.us.debian.org/debian/pool/main/libx/libx11/libx11-dev_1.6.4-3_i386.deb http://ftp.us.debian.org/debian/pool/main/libx/libx11/libx11-xcb1_1.6.4-3_i386.deb @@ -122,10 +140,9 @@ http://ftp.us.debian.org/debian/pool/main/libx/libxcb/libxcb-shm0_1.12-1_i386.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcb/libxcb-shm0-dev_1.12-1_i386.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcb/libxcb-sync1_1.12-1_i386.deb +http://ftp.us.debian.org/debian/pool/main/libx/libxcb/libxcb-xfixes0_1.12-1_i386.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcomposite/libxcomposite1_0.4.4-2_i386.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcomposite/libxcomposite-dev_0.4.4-2_i386.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxcursor/libxcursor1_1.1.14-1+b4_i386.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxcursor/libxcursor-dev_1.1.14-1+b4_i386.deb http://ftp.us.debian.org/debian/pool/main/libx/libxdamage/libxdamage1_1.1.4-2+b3_i386.deb http://ftp.us.debian.org/debian/pool/main/libx/libxdamage/libxdamage-dev_1.1.4-2+b3_i386.deb http://ftp.us.debian.org/debian/pool/main/libx/libxdmcp/libxdmcp6_1.1.2-3_i386.deb @@ -138,8 +155,8 @@ http://ftp.us.debian.org/debian/pool/main/libx/libxi/libxi-dev_1.7.9-1_i386.deb http://ftp.us.debian.org/debian/pool/main/libx/libxinerama/libxinerama1_1.1.3-1+b3_i386.deb http://ftp.us.debian.org/debian/pool/main/libx/libxinerama/libxinerama-dev_1.1.3-1+b3_i386.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon0_0.7.1-1_i386.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon-dev_0.7.1-1_i386.deb +http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon0_0.7.1-2~deb9u1_i386.deb +http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon-dev_0.7.1-2~deb9u1_i386.deb http://ftp.us.debian.org/debian/pool/main/libx/libxrandr/libxrandr2_1.5.1-1_i386.deb http://ftp.us.debian.org/debian/pool/main/libx/libxrandr/libxrandr-dev_1.5.1-1_i386.deb http://ftp.us.debian.org/debian/pool/main/libx/libxrender/libxrender1_0.9.10-1_i386.deb @@ -152,6 +169,9 @@ http://ftp.us.debian.org/debian/pool/main/libx/libxtst/libxtst6_1.2.3-1_i386.deb http://ftp.us.debian.org/debian/pool/main/libx/libxtst/libxtst-dev_1.2.3-1_i386.deb http://ftp.us.debian.org/debian/pool/main/libx/libxxf86vm/libxxf86vm1_1.1.4-1+b2_i386.deb +http://ftp.us.debian.org/debian/pool/main/l/lcms2/liblcms2-2_2.8-4_i386.deb +http://ftp.us.debian.org/debian/pool/main/l/lz4/liblz4-1_0.0~r131-2+b1_i386.deb +http://ftp.us.debian.org/debian/pool/main/l/lzo2/liblzo2-2_2.08-1.2+b2_i386.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/libegl1-mesa_13.0.6-1+b2_i386.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/libegl1-mesa-dev_13.0.6-1+b2_i386.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/libgbm1_13.0.6-1+b2_i386.deb @@ -161,8 +181,11 @@ http://ftp.us.debian.org/debian/pool/main/m/mesa/libglapi-mesa_13.0.6-1+b2_i386.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/libwayland-egl1-mesa_13.0.6-1+b2_i386.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/mesa-common-dev_13.0.6-1+b2_i386.deb +http://ftp.us.debian.org/debian/pool/main/n/nettle/libhogweed4_3.3-1+b2_i386.deb +http://ftp.us.debian.org/debian/pool/main/n/nettle/libnettle6_3.3-1+b2_i386.deb http://ftp.us.debian.org/debian/pool/main/n/nspr/libnspr4_4.12-6_i386.deb http://ftp.us.debian.org/debian/pool/main/n/nspr/libnspr4-dev_4.12-6_i386.deb +http://ftp.us.debian.org/debian/pool/main/o/orbit2/liborbit-2-0_2.14.19-2+b1_i386.deb http://ftp.us.debian.org/debian/pool/main/o/orbit2/liborbit2_2.14.19-2+b1_i386.deb http://ftp.us.debian.org/debian/pool/main/p/p11-kit/libp11-kit0_0.23.3-2_i386.deb http://ftp.us.debian.org/debian/pool/main/p/pam/libpam0g_1.1.8-3.6_i386.deb @@ -188,8 +211,15 @@ http://ftp.us.debian.org/debian/pool/main/s/speech-dispatcher/libspeechd2_0.8.6-4+deb9u1_i386.deb http://ftp.us.debian.org/debian/pool/main/s/speech-dispatcher/libspeechd-dev_0.8.6-4+deb9u1_i386.deb http://ftp.us.debian.org/debian/pool/main/s/speech-dispatcher/speech-dispatcher_0.8.6-4+deb9u1_i386.deb +http://ftp.us.debian.org/debian/pool/main/s/sqlite3/libsqlite3-0_3.16.2-5+deb9u1_i386.deb +http://ftp.us.debian.org/debian/pool/main/s/systemd/libsystemd0_232-25+deb9u1_i386.deb http://ftp.us.debian.org/debian/pool/main/s/systemd/libudev1_232-25+deb9u1_i386.deb http://ftp.us.debian.org/debian/pool/main/s/systemd/libudev-dev_232-25+deb9u1_i386.deb +http://ftp.us.debian.org/debian/pool/main/t/tcp-wrappers/libwrap0_7.6.q-26_i386.deb +http://ftp.us.debian.org/debian/pool/main/u/unbound/libunbound2_1.6.0-3+deb9u1_i386.deb +http://ftp.us.debian.org/debian/pool/main/u/util-linux/libblkid1_2.29.2-1_i386.deb +http://ftp.us.debian.org/debian/pool/main/u/util-linux/libmount1_2.29.2-1_i386.deb +http://ftp.us.debian.org/debian/pool/main/u/util-linux/libuuid1_2.29.2-1_i386.deb http://ftp.us.debian.org/debian/pool/main/w/wayland/libwayland-client0_1.12.0-1_i386.deb http://ftp.us.debian.org/debian/pool/main/w/wayland/libwayland-cursor0_1.12.0-1_i386.deb http://ftp.us.debian.org/debian/pool/main/w/wayland/libwayland-dev_1.12.0-1_i386.deb @@ -207,6 +237,8 @@ http://ftp.us.debian.org/debian/pool/main/x/x11proto-scrnsaver/x11proto-scrnsaver-dev_1.2.2-1_all.deb http://ftp.us.debian.org/debian/pool/main/x/x11proto-xext/x11proto-xext-dev_7.3.0-1_all.deb http://ftp.us.debian.org/debian/pool/main/x/x11proto-xinerama/x11proto-xinerama-dev_1.2.1-2_all.deb +http://ftp.us.debian.org/debian/pool/main/x/xft/libxft2_2.3.2-1+b2_i386.deb +http://ftp.us.debian.org/debian/pool/main/x/xz-utils/liblzma5_5.2.2-1.2+b1_i386.deb http://ftp.us.debian.org/debian/pool/main/z/zlib/zlib1g_1.2.8.dfsg-5_i386.deb http://ftp.us.debian.org/debian/pool/main/z/zlib/zlib1g-dev_1.2.8.dfsg-5_i386.deb http://security.debian.org/pool/updates/main/b/bluez/libbluetooth3_5.43-2+deb9u1_i386.deb @@ -224,9 +256,15 @@ http://security.debian.org/pool/updates/main/g/gnutls28/libgnutlsxx28_3.5.8-5+deb9u1_i386.deb http://security.debian.org/pool/updates/main/libg/libgcrypt20/libgcrypt20_1.7.6-2+deb9u2_i386.deb http://security.debian.org/pool/updates/main/libg/libgcrypt20/libgcrypt20-dev_1.7.6-2+deb9u2_i386.deb +http://security.debian.org/pool/updates/main/libs/libsoup2.4/libsoup2.4-1_2.56.0-2+deb9u1_i386.deb +http://security.debian.org/pool/updates/main/libs/libsoup2.4/libsoup-gnome2.4-1_2.56.0-2+deb9u1_i386.deb +http://security.debian.org/pool/updates/main/libx/libxcursor/libxcursor1_1.1.14-1+deb9u1_i386.deb +http://security.debian.org/pool/updates/main/libx/libxcursor/libxcursor-dev_1.1.14-1+deb9u1_i386.deb +http://security.debian.org/pool/updates/main/libx/libxml2/libxml2_2.9.4+dfsg1-2.2+deb9u1_i386.deb http://security.debian.org/pool/updates/main/l/linux/linux-libc-dev_4.9.30-2+deb9u5_i386.deb http://security.debian.org/pool/updates/main/n/nss/libnss3_3.26.2-1.1+deb9u1_i386.deb http://security.debian.org/pool/updates/main/n/nss/libnss3-dev_3.26.2-1.1+deb9u1_i386.deb http://security.debian.org/pool/updates/main/o/openssl1.0/libssl1.0.2_1.0.2l-2+deb9u1_i386.deb http://security.debian.org/pool/updates/main/o/openssl/libssl1.1_1.1.0f-3+deb9u1_i386.deb http://security.debian.org/pool/updates/main/o/openssl/libssl-dev_1.1.0f-3+deb9u1_i386.deb +http://security.debian.org/pool/updates/main/t/tiff/libtiff5_4.0.8-2+deb9u1_i386.deb
diff --git a/build/linux/sysroot_scripts/packagelist.stretch.mips64el b/build/linux/sysroot_scripts/packagelist.stretch.mips64el index 7390896a..594ac06 100644 --- a/build/linux/sysroot_scripts/packagelist.stretch.mips64el +++ b/build/linux/sysroot_scripts/packagelist.stretch.mips64el
@@ -16,19 +16,20 @@ http://ftp.us.debian.org/debian/pool/main/c/cairo/libcairo2-dev_1.14.8-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/c/cairo/libcairo-gobject2_1.14.8-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/c/cairo/libcairo-script-interpreter2_1.14.8-1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/c/colord/libcolord2_1.3.3-2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/c/cups/libcups2_2.2.1-8_mips64el.deb http://ftp.us.debian.org/debian/pool/main/c/cups/libcups2-dev_2.2.1-8_mips64el.deb http://ftp.us.debian.org/debian/pool/main/c/cups/libcupsimage2_2.2.1-8_mips64el.deb http://ftp.us.debian.org/debian/pool/main/c/cups/libcupsimage2-dev_2.2.1-8_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/d/db5.3/libdb5.3_5.3.28-12+deb9u1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/d/dbus-glib/libdbus-glib-1-2_0.108-2_mips64el.deb -http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-3_1.10.22-0+deb9u1_mips64el.deb -http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-dev_1.10.22-0+deb9u1_mips64el.deb -http://ftp.us.debian.org/debian/pool/main/d/d-conf/libdconf1_0.26.0-2+b1_mips64el.deb -http://ftp.us.debian.org/debian/pool/main/d/d-conf/libdconf-dev_0.26.0-2+b1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-3_1.10.24-0+deb9u1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-dev_1.10.24-0+deb9u1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/e/e2fsprogs/comerr-dev_2.1-1.43.4-2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/e/e2fsprogs/libcomerr2_1.43.4-2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/e/elfutils/libelf1_0.168-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/e/elfutils/libelf-dev_0.168-1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/f/flac/libflac8_1.3.2-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/f/fontconfig/libfontconfig1_2.11.0-6.7+b1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/f/fontconfig/libfontconfig1-dev_2.11.0-6.7+b1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/f/freetype/libfreetype6_2.6.3-3.2_mips64el.deb @@ -39,11 +40,9 @@ http://ftp.us.debian.org/debian/pool/main/g/gcc-6/libgomp1_6.3.0-18_mips64el.deb http://ftp.us.debian.org/debian/pool/main/g/gcc-6/libstdc++6_6.3.0-18_mips64el.deb http://ftp.us.debian.org/debian/pool/main/g/gcc-6/libstdc++-6-dev_6.3.0-18_mips64el.deb -http://ftp.us.debian.org/debian/pool/main/g/gconf/libgconf-2-4_3.2.6-4+b1_mips64el.deb -http://ftp.us.debian.org/debian/pool/main/g/gconf/libgconf2-4_3.2.6-4+b1_mips64el.deb -http://ftp.us.debian.org/debian/pool/main/g/gconf/libgconf2-dev_3.2.6-4+b1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/g/glib2.0/libglib2.0-0_2.50.3-2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/g/glib2.0/libglib2.0-dev_2.50.3-2_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/g/gmp/libgmp10_6.1.2+dfsg-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/g/graphite2/libgraphite2-3_1.3.10-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/g/graphite2/libgraphite2-dev_1.3.10-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/g/gtk+2.0/libgtk2.0-0_2.24.31-2_mips64el.deb @@ -54,6 +53,9 @@ http://ftp.us.debian.org/debian/pool/main/h/harfbuzz/libharfbuzz-dev_1.4.2-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/h/harfbuzz/libharfbuzz-gobject0_1.4.2-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/h/harfbuzz/libharfbuzz-icu0_1.4.2-1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/i/icu/libicu57_57.1-6+deb9u1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/j/jbigkit/libjbig0_2.1-3.1+b2_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/j/json-glib/libjson-glib-1.0-0_1.2.6-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/k/keyutils/libkeyutils1_1.5.9-9_mips64el.deb http://ftp.us.debian.org/debian/pool/main/k/krb5/krb5-multidev_1.15-1+deb9u1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/k/krb5/libgssapi-krb5-2_1.15-1+deb9u1_mips64el.deb @@ -65,9 +67,12 @@ http://ftp.us.debian.org/debian/pool/main/k/krb5/libkrb5-3_1.15-1+deb9u1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/k/krb5/libkrb5-dev_1.15-1+deb9u1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/k/krb5/libkrb5support0_1.15-1+deb9u1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/liba/libasyncns/libasyncns0_0.8-6_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libb/libbsd/libbsd0_0.8.3-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libc/libcap2/libcap2_2.25-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libc/libcap2/libcap-dev_2.25-1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/libc/libcap-ng/libcap-ng0_0.7.7-3+b1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/libd/libdatrie/libdatrie1_0.2.10-4+b1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libd/libdrm/libdrm2_2.4.74-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libd/libdrm/libdrm-amdgpu1_2.4.74-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libd/libdrm/libdrm-dev_2.4.74-1_mips64el.deb @@ -81,15 +86,26 @@ http://ftp.us.debian.org/debian/pool/main/libg/libgnome-keyring/libgnome-keyring-dev_3.12.0-1+b2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libg/libgpg-error/libgpg-error0_1.26-2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libg/libgpg-error/libgpg-error-dev_1.26-2_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/libi/libice/libice6_1.0.9-2_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/libi/libidl/libidl-2-0_0.8.14-4_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/libi/libidn/libidn11_1.33-1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/libj/libjpeg-turbo/libjpeg62-turbo_1.5.1-2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libj/libjsoncpp/libjsoncpp1_1.7.4-3_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libj/libjsoncpp/libjsoncpp-dev_1.7.4-3_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libn/libnss-db/libnss-db_2.2.3pre1-6+b1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/libo/libogg/libogg0_1.3.2-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libp/libp11/libp11-2_0.4.3-1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/libp/libpciaccess/libpciaccess0_0.13.4-1+b2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libp/libpng1.6/libpng16-16_1.6.28-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libp/libpng1.6/libpng-dev_1.6.28-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libp/libpthread-stubs/libpthread-stubs0-dev_0.3-4_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/libr/librest/librest-0.7-0_0.8.0-2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libs/libselinux/libselinux1_2.6-3+b3_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/libs/libsm/libsm6_1.2.2-1+b3_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/libs/libsndfile/libsndfile1_1.0.27-3_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libt/libtasn1-6/libtasn1-6_4.10-1.1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/libt/libthai/libthai0_0.1.26-1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/libt/libtool/libltdl7_2.4.6-2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva1_1.7.3-2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-dev_1.7.3-2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-drm1_1.7.3-2_mips64el.deb @@ -98,6 +114,8 @@ http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-tpi1_1.7.3-2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-wayland1_1.7.3-2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-x11-1_1.7.3-2_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/libv/libvorbis/libvorbis0a_1.3.5-4_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/libv/libvorbis/libvorbisenc2_1.3.5-4_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libx/libx11/libx11-6_1.6.4-3_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libx/libx11/libx11-dev_1.6.4-3_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libx/libx11/libx11-xcb1_1.6.4-3_mips64el.deb @@ -115,10 +133,9 @@ http://ftp.us.debian.org/debian/pool/main/libx/libxcb/libxcb-shm0_1.12-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcb/libxcb-shm0-dev_1.12-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcb/libxcb-sync1_1.12-1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/libx/libxcb/libxcb-xfixes0_1.12-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcomposite/libxcomposite1_0.4.4-2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcomposite/libxcomposite-dev_0.4.4-2_mips64el.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxcursor/libxcursor1_1.1.14-1+b4_mips64el.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxcursor/libxcursor-dev_1.1.14-1+b4_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libx/libxdamage/libxdamage1_1.1.4-2+b3_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libx/libxdamage/libxdamage-dev_1.1.4-2+b3_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libx/libxdmcp/libxdmcp6_1.1.2-3_mips64el.deb @@ -131,8 +148,8 @@ http://ftp.us.debian.org/debian/pool/main/libx/libxi/libxi-dev_1.7.9-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libx/libxinerama/libxinerama1_1.1.3-1+b3_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libx/libxinerama/libxinerama-dev_1.1.3-1+b3_mips64el.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon0_0.7.1-1_mips64el.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon-dev_0.7.1-1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon0_0.7.1-2~deb9u1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon-dev_0.7.1-2~deb9u1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libx/libxrandr/libxrandr2_1.5.1-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libx/libxrandr/libxrandr-dev_1.5.1-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libx/libxrender/libxrender1_0.9.10-1_mips64el.deb @@ -145,6 +162,9 @@ http://ftp.us.debian.org/debian/pool/main/libx/libxtst/libxtst6_1.2.3-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libx/libxtst/libxtst-dev_1.2.3-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/libx/libxxf86vm/libxxf86vm1_1.1.4-1+b2_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/l/lcms2/liblcms2-2_2.8-4_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/l/lz4/liblz4-1_0.0~r131-2+b1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/l/lzo2/liblzo2-2_2.08-1.2+b2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/libegl1-mesa_13.0.6-1+b2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/libegl1-mesa-dev_13.0.6-1+b2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/libgbm1_13.0.6-1+b2_mips64el.deb @@ -154,8 +174,11 @@ http://ftp.us.debian.org/debian/pool/main/m/mesa/libglapi-mesa_13.0.6-1+b2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/libwayland-egl1-mesa_13.0.6-1+b2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/mesa-common-dev_13.0.6-1+b2_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/n/nettle/libhogweed4_3.3-1+b2_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/n/nettle/libnettle6_3.3-1+b2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/n/nspr/libnspr4_4.12-6_mips64el.deb http://ftp.us.debian.org/debian/pool/main/n/nspr/libnspr4-dev_4.12-6_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/o/orbit2/liborbit-2-0_2.14.19-2+b1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/o/orbit2/liborbit2_2.14.19-2+b1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/p/p11-kit/libp11-kit0_0.23.3-2_mips64el.deb http://ftp.us.debian.org/debian/pool/main/p/pam/libpam0g_1.1.8-3.6_mips64el.deb @@ -181,8 +204,15 @@ http://ftp.us.debian.org/debian/pool/main/s/speech-dispatcher/libspeechd2_0.8.6-4+deb9u1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/s/speech-dispatcher/libspeechd-dev_0.8.6-4+deb9u1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/s/speech-dispatcher/speech-dispatcher_0.8.6-4+deb9u1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/s/sqlite3/libsqlite3-0_3.16.2-5+deb9u1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/s/systemd/libsystemd0_232-25+deb9u1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/s/systemd/libudev1_232-25+deb9u1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/s/systemd/libudev-dev_232-25+deb9u1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/t/tcp-wrappers/libwrap0_7.6.q-26_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/u/unbound/libunbound2_1.6.0-3+deb9u1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/u/util-linux/libblkid1_2.29.2-1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/u/util-linux/libmount1_2.29.2-1_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/u/util-linux/libuuid1_2.29.2-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/w/wayland/libwayland-client0_1.12.0-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/w/wayland/libwayland-cursor0_1.12.0-1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/w/wayland/libwayland-dev_1.12.0-1_mips64el.deb @@ -200,6 +230,8 @@ http://ftp.us.debian.org/debian/pool/main/x/x11proto-scrnsaver/x11proto-scrnsaver-dev_1.2.2-1_all.deb http://ftp.us.debian.org/debian/pool/main/x/x11proto-xext/x11proto-xext-dev_7.3.0-1_all.deb http://ftp.us.debian.org/debian/pool/main/x/x11proto-xinerama/x11proto-xinerama-dev_1.2.1-2_all.deb +http://ftp.us.debian.org/debian/pool/main/x/xft/libxft2_2.3.2-1+b2_mips64el.deb +http://ftp.us.debian.org/debian/pool/main/x/xz-utils/liblzma5_5.2.2-1.2+b1_mips64el.deb http://ftp.us.debian.org/debian/pool/main/z/zlib/zlib1g_1.2.8.dfsg-5_mips64el.deb http://ftp.us.debian.org/debian/pool/main/z/zlib/zlib1g-dev_1.2.8.dfsg-5_mips64el.deb http://security.debian.org/pool/updates/main/b/bluez/libbluetooth3_5.43-2+deb9u1_mips64el.deb @@ -217,9 +249,15 @@ http://security.debian.org/pool/updates/main/g/gnutls28/libgnutlsxx28_3.5.8-5+deb9u1_mips64el.deb http://security.debian.org/pool/updates/main/libg/libgcrypt20/libgcrypt20_1.7.6-2+deb9u2_mips64el.deb http://security.debian.org/pool/updates/main/libg/libgcrypt20/libgcrypt20-dev_1.7.6-2+deb9u2_mips64el.deb +http://security.debian.org/pool/updates/main/libs/libsoup2.4/libsoup2.4-1_2.56.0-2+deb9u1_mips64el.deb +http://security.debian.org/pool/updates/main/libs/libsoup2.4/libsoup-gnome2.4-1_2.56.0-2+deb9u1_mips64el.deb +http://security.debian.org/pool/updates/main/libx/libxcursor/libxcursor1_1.1.14-1+deb9u1_mips64el.deb +http://security.debian.org/pool/updates/main/libx/libxcursor/libxcursor-dev_1.1.14-1+deb9u1_mips64el.deb +http://security.debian.org/pool/updates/main/libx/libxml2/libxml2_2.9.4+dfsg1-2.2+deb9u1_mips64el.deb http://security.debian.org/pool/updates/main/l/linux/linux-libc-dev_4.9.30-2+deb9u5_mips64el.deb http://security.debian.org/pool/updates/main/n/nss/libnss3_3.26.2-1.1+deb9u1_mips64el.deb http://security.debian.org/pool/updates/main/n/nss/libnss3-dev_3.26.2-1.1+deb9u1_mips64el.deb http://security.debian.org/pool/updates/main/o/openssl1.0/libssl1.0.2_1.0.2l-2+deb9u1_mips64el.deb http://security.debian.org/pool/updates/main/o/openssl/libssl1.1_1.1.0f-3+deb9u1_mips64el.deb http://security.debian.org/pool/updates/main/o/openssl/libssl-dev_1.1.0f-3+deb9u1_mips64el.deb +http://security.debian.org/pool/updates/main/t/tiff/libtiff5_4.0.8-2+deb9u1_mips64el.deb
diff --git a/build/linux/sysroot_scripts/packagelist.stretch.mipsel b/build/linux/sysroot_scripts/packagelist.stretch.mipsel index 8fd9d5b..a825f57b 100644 --- a/build/linux/sysroot_scripts/packagelist.stretch.mipsel +++ b/build/linux/sysroot_scripts/packagelist.stretch.mipsel
@@ -16,19 +16,20 @@ http://ftp.us.debian.org/debian/pool/main/c/cairo/libcairo2-dev_1.14.8-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/c/cairo/libcairo-gobject2_1.14.8-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/c/cairo/libcairo-script-interpreter2_1.14.8-1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/c/colord/libcolord2_1.3.3-2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/c/cups/libcups2_2.2.1-8_mipsel.deb http://ftp.us.debian.org/debian/pool/main/c/cups/libcups2-dev_2.2.1-8_mipsel.deb http://ftp.us.debian.org/debian/pool/main/c/cups/libcupsimage2_2.2.1-8_mipsel.deb http://ftp.us.debian.org/debian/pool/main/c/cups/libcupsimage2-dev_2.2.1-8_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/d/db5.3/libdb5.3_5.3.28-12+deb9u1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/d/dbus-glib/libdbus-glib-1-2_0.108-2_mipsel.deb -http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-3_1.10.22-0+deb9u1_mipsel.deb -http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-dev_1.10.22-0+deb9u1_mipsel.deb -http://ftp.us.debian.org/debian/pool/main/d/d-conf/libdconf1_0.26.0-2+b1_mipsel.deb -http://ftp.us.debian.org/debian/pool/main/d/d-conf/libdconf-dev_0.26.0-2+b1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-3_1.10.24-0+deb9u1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/d/dbus/libdbus-1-dev_1.10.24-0+deb9u1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/e/e2fsprogs/comerr-dev_2.1-1.43.4-2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/e/e2fsprogs/libcomerr2_1.43.4-2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/e/elfutils/libelf1_0.168-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/e/elfutils/libelf-dev_0.168-1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/f/flac/libflac8_1.3.2-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/f/fontconfig/libfontconfig1_2.11.0-6.7+b1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/f/fontconfig/libfontconfig1-dev_2.11.0-6.7+b1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/f/freetype/libfreetype6_2.6.3-3.2_mipsel.deb @@ -39,11 +40,9 @@ http://ftp.us.debian.org/debian/pool/main/g/gcc-6/libgomp1_6.3.0-18_mipsel.deb http://ftp.us.debian.org/debian/pool/main/g/gcc-6/libstdc++6_6.3.0-18_mipsel.deb http://ftp.us.debian.org/debian/pool/main/g/gcc-6/libstdc++-6-dev_6.3.0-18_mipsel.deb -http://ftp.us.debian.org/debian/pool/main/g/gconf/libgconf2-4_3.2.6-4+b1_mipsel.deb -http://ftp.us.debian.org/debian/pool/main/g/gconf/libgconf-2-4_3.2.6-4+b1_mipsel.deb -http://ftp.us.debian.org/debian/pool/main/g/gconf/libgconf2-dev_3.2.6-4+b1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/g/glib2.0/libglib2.0-0_2.50.3-2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/g/glib2.0/libglib2.0-dev_2.50.3-2_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/g/gmp/libgmp10_6.1.2+dfsg-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/g/graphite2/libgraphite2-3_1.3.10-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/g/graphite2/libgraphite2-dev_1.3.10-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/g/gtk+2.0/libgtk2.0-0_2.24.31-2_mipsel.deb @@ -54,6 +53,9 @@ http://ftp.us.debian.org/debian/pool/main/h/harfbuzz/libharfbuzz-dev_1.4.2-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/h/harfbuzz/libharfbuzz-gobject0_1.4.2-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/h/harfbuzz/libharfbuzz-icu0_1.4.2-1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/i/icu/libicu57_57.1-6+deb9u1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/j/jbigkit/libjbig0_2.1-3.1+b2_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/j/json-glib/libjson-glib-1.0-0_1.2.6-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/k/keyutils/libkeyutils1_1.5.9-9_mipsel.deb http://ftp.us.debian.org/debian/pool/main/k/krb5/krb5-multidev_1.15-1+deb9u1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/k/krb5/libgssapi-krb5-2_1.15-1+deb9u1_mipsel.deb @@ -65,9 +67,12 @@ http://ftp.us.debian.org/debian/pool/main/k/krb5/libkrb5-3_1.15-1+deb9u1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/k/krb5/libkrb5-dev_1.15-1+deb9u1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/k/krb5/libkrb5support0_1.15-1+deb9u1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/liba/libasyncns/libasyncns0_0.8-6_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libb/libbsd/libbsd0_0.8.3-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libc/libcap2/libcap2_2.25-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libc/libcap2/libcap-dev_2.25-1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/libc/libcap-ng/libcap-ng0_0.7.7-3+b1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/libd/libdatrie/libdatrie1_0.2.10-4+b1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libd/libdrm/libdrm2_2.4.74-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libd/libdrm/libdrm-amdgpu1_2.4.74-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libd/libdrm/libdrm-dev_2.4.74-1_mipsel.deb @@ -81,15 +86,26 @@ http://ftp.us.debian.org/debian/pool/main/libg/libgnome-keyring/libgnome-keyring-dev_3.12.0-1+b2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libg/libgpg-error/libgpg-error0_1.26-2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libg/libgpg-error/libgpg-error-dev_1.26-2_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/libi/libice/libice6_1.0.9-2_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/libi/libidl/libidl-2-0_0.8.14-4_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/libi/libidn/libidn11_1.33-1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/libj/libjpeg-turbo/libjpeg62-turbo_1.5.1-2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libj/libjsoncpp/libjsoncpp1_1.7.4-3_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libj/libjsoncpp/libjsoncpp-dev_1.7.4-3_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libn/libnss-db/libnss-db_2.2.3pre1-6+b1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/libo/libogg/libogg0_1.3.2-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libp/libp11/libp11-2_0.4.3-1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/libp/libpciaccess/libpciaccess0_0.13.4-1+b2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libp/libpng1.6/libpng16-16_1.6.28-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libp/libpng1.6/libpng-dev_1.6.28-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libp/libpthread-stubs/libpthread-stubs0-dev_0.3-4_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/libr/librest/librest-0.7-0_0.8.0-2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libs/libselinux/libselinux1_2.6-3+b3_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/libs/libsm/libsm6_1.2.2-1+b3_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/libs/libsndfile/libsndfile1_1.0.27-3_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libt/libtasn1-6/libtasn1-6_4.10-1.1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/libt/libthai/libthai0_0.1.26-1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/libt/libtool/libltdl7_2.4.6-2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva1_1.7.3-2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-dev_1.7.3-2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-drm1_1.7.3-2_mipsel.deb @@ -98,6 +114,8 @@ http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-tpi1_1.7.3-2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-wayland1_1.7.3-2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libv/libva/libva-x11-1_1.7.3-2_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/libv/libvorbis/libvorbis0a_1.3.5-4_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/libv/libvorbis/libvorbisenc2_1.3.5-4_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libx/libx11/libx11-6_1.6.4-3_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libx/libx11/libx11-dev_1.6.4-3_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libx/libx11/libx11-xcb1_1.6.4-3_mipsel.deb @@ -115,10 +133,9 @@ http://ftp.us.debian.org/debian/pool/main/libx/libxcb/libxcb-shm0_1.12-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcb/libxcb-shm0-dev_1.12-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcb/libxcb-sync1_1.12-1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/libx/libxcb/libxcb-xfixes0_1.12-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcomposite/libxcomposite1_0.4.4-2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libx/libxcomposite/libxcomposite-dev_0.4.4-2_mipsel.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxcursor/libxcursor1_1.1.14-1+b4_mipsel.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxcursor/libxcursor-dev_1.1.14-1+b4_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libx/libxdamage/libxdamage1_1.1.4-2+b3_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libx/libxdamage/libxdamage-dev_1.1.4-2+b3_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libx/libxdmcp/libxdmcp6_1.1.2-3_mipsel.deb @@ -131,8 +148,8 @@ http://ftp.us.debian.org/debian/pool/main/libx/libxi/libxi-dev_1.7.9-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libx/libxinerama/libxinerama1_1.1.3-1+b3_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libx/libxinerama/libxinerama-dev_1.1.3-1+b3_mipsel.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon0_0.7.1-1_mipsel.deb -http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon-dev_0.7.1-1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon0_0.7.1-2~deb9u1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/libx/libxkbcommon/libxkbcommon-dev_0.7.1-2~deb9u1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libx/libxrandr/libxrandr2_1.5.1-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libx/libxrandr/libxrandr-dev_1.5.1-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libx/libxrender/libxrender1_0.9.10-1_mipsel.deb @@ -145,6 +162,9 @@ http://ftp.us.debian.org/debian/pool/main/libx/libxtst/libxtst6_1.2.3-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libx/libxtst/libxtst-dev_1.2.3-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/libx/libxxf86vm/libxxf86vm1_1.1.4-1+b2_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/l/lcms2/liblcms2-2_2.8-4_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/l/lz4/liblz4-1_0.0~r131-2+b1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/l/lzo2/liblzo2-2_2.08-1.2+b2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/libegl1-mesa_13.0.6-1+b2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/libegl1-mesa-dev_13.0.6-1+b2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/libgbm1_13.0.6-1+b2_mipsel.deb @@ -154,8 +174,11 @@ http://ftp.us.debian.org/debian/pool/main/m/mesa/libglapi-mesa_13.0.6-1+b2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/libwayland-egl1-mesa_13.0.6-1+b2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/m/mesa/mesa-common-dev_13.0.6-1+b2_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/n/nettle/libhogweed4_3.3-1+b2_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/n/nettle/libnettle6_3.3-1+b2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/n/nspr/libnspr4_4.12-6_mipsel.deb http://ftp.us.debian.org/debian/pool/main/n/nspr/libnspr4-dev_4.12-6_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/o/orbit2/liborbit-2-0_2.14.19-2+b1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/o/orbit2/liborbit2_2.14.19-2+b1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/p/p11-kit/libp11-kit0_0.23.3-2_mipsel.deb http://ftp.us.debian.org/debian/pool/main/p/pam/libpam0g_1.1.8-3.6_mipsel.deb @@ -181,8 +204,15 @@ http://ftp.us.debian.org/debian/pool/main/s/speech-dispatcher/libspeechd2_0.8.6-4+deb9u1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/s/speech-dispatcher/libspeechd-dev_0.8.6-4+deb9u1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/s/speech-dispatcher/speech-dispatcher_0.8.6-4+deb9u1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/s/sqlite3/libsqlite3-0_3.16.2-5+deb9u1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/s/systemd/libsystemd0_232-25+deb9u1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/s/systemd/libudev1_232-25+deb9u1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/s/systemd/libudev-dev_232-25+deb9u1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/t/tcp-wrappers/libwrap0_7.6.q-26_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/u/unbound/libunbound2_1.6.0-3+deb9u1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/u/util-linux/libblkid1_2.29.2-1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/u/util-linux/libmount1_2.29.2-1_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/u/util-linux/libuuid1_2.29.2-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/w/wayland/libwayland-client0_1.12.0-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/w/wayland/libwayland-cursor0_1.12.0-1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/w/wayland/libwayland-dev_1.12.0-1_mipsel.deb @@ -200,6 +230,8 @@ http://ftp.us.debian.org/debian/pool/main/x/x11proto-scrnsaver/x11proto-scrnsaver-dev_1.2.2-1_all.deb http://ftp.us.debian.org/debian/pool/main/x/x11proto-xext/x11proto-xext-dev_7.3.0-1_all.deb http://ftp.us.debian.org/debian/pool/main/x/x11proto-xinerama/x11proto-xinerama-dev_1.2.1-2_all.deb +http://ftp.us.debian.org/debian/pool/main/x/xft/libxft2_2.3.2-1+b2_mipsel.deb +http://ftp.us.debian.org/debian/pool/main/x/xz-utils/liblzma5_5.2.2-1.2+b1_mipsel.deb http://ftp.us.debian.org/debian/pool/main/z/zlib/zlib1g_1.2.8.dfsg-5_mipsel.deb http://ftp.us.debian.org/debian/pool/main/z/zlib/zlib1g-dev_1.2.8.dfsg-5_mipsel.deb http://security.debian.org/pool/updates/main/b/bluez/libbluetooth3_5.43-2+deb9u1_mipsel.deb @@ -217,9 +249,15 @@ http://security.debian.org/pool/updates/main/g/gnutls28/libgnutlsxx28_3.5.8-5+deb9u1_mipsel.deb http://security.debian.org/pool/updates/main/libg/libgcrypt20/libgcrypt20_1.7.6-2+deb9u2_mipsel.deb http://security.debian.org/pool/updates/main/libg/libgcrypt20/libgcrypt20-dev_1.7.6-2+deb9u2_mipsel.deb +http://security.debian.org/pool/updates/main/libs/libsoup2.4/libsoup2.4-1_2.56.0-2+deb9u1_mipsel.deb +http://security.debian.org/pool/updates/main/libs/libsoup2.4/libsoup-gnome2.4-1_2.56.0-2+deb9u1_mipsel.deb +http://security.debian.org/pool/updates/main/libx/libxcursor/libxcursor1_1.1.14-1+deb9u1_mipsel.deb +http://security.debian.org/pool/updates/main/libx/libxcursor/libxcursor-dev_1.1.14-1+deb9u1_mipsel.deb +http://security.debian.org/pool/updates/main/libx/libxml2/libxml2_2.9.4+dfsg1-2.2+deb9u1_mipsel.deb http://security.debian.org/pool/updates/main/l/linux/linux-libc-dev_4.9.30-2+deb9u5_mipsel.deb http://security.debian.org/pool/updates/main/n/nss/libnss3_3.26.2-1.1+deb9u1_mipsel.deb http://security.debian.org/pool/updates/main/n/nss/libnss3-dev_3.26.2-1.1+deb9u1_mipsel.deb http://security.debian.org/pool/updates/main/o/openssl1.0/libssl1.0.2_1.0.2l-2+deb9u1_mipsel.deb http://security.debian.org/pool/updates/main/o/openssl/libssl1.1_1.1.0f-3+deb9u1_mipsel.deb http://security.debian.org/pool/updates/main/o/openssl/libssl-dev_1.1.0f-3+deb9u1_mipsel.deb +http://security.debian.org/pool/updates/main/t/tiff/libtiff5_4.0.8-2+deb9u1_mipsel.deb
diff --git a/build/linux/sysroot_scripts/sysroot-creator-stretch.sh b/build/linux/sysroot_scripts/sysroot-creator-stretch.sh index a0e50aba..077abd54 100755 --- a/build/linux/sysroot_scripts/sysroot-creator-stretch.sh +++ b/build/linux/sysroot_scripts/sysroot-creator-stretch.sh
@@ -72,8 +72,6 @@ libdbus-1-3 libdbus-1-dev libdbus-glib-1-2 - libdconf-dev - libdconf1 libdrm-amdgpu1 libdrm-dev libdrm-nouveau2 @@ -98,9 +96,6 @@ libgbm1 libgcc-6-dev libgcc1 - libgconf-2-4 - libgconf2-4 - libgconf2-dev libgcrypt20 libgcrypt20-dev libgdk-pixbuf2.0-0
diff --git a/build/linux/unbundle/freetype.gn b/build/linux/unbundle/freetype.gn index 0d80fd7f..cafa9db6b 100644 --- a/build/linux/unbundle/freetype.gn +++ b/build/linux/unbundle/freetype.gn
@@ -2,124 +2,13 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/config/linux/pkg_config.gni") -import("//build/shim_headers.gni") - -pkg_config("freetype_config") { - packages = [ "freetype2" ] -} - -shim_headers("freetype_shim") { - root_path = "src/include" - headers = [ - # This list can easily be updated using the command below: - # find third_party/freetype/src/include \ - # -iname '*.h' -printf '"%p",\n' | \ - # sed -e 's|third_party/freetype/src/include/||' | sort -u - "freetype/config/ftconfig.h", - "freetype/config/ftheader.h", - "freetype/config/ftmodule.h", - "freetype/config/ftoption.h", - "freetype/config/ftstdlib.h", - "freetype/freetype.h", - "freetype/ftadvanc.h", - "freetype/ftautoh.h", - "freetype/ftbbox.h", - "freetype/ftbdf.h", - "freetype/ftbitmap.h", - "freetype/ftbzip2.h", - "freetype/ftcache.h", - "freetype/ftcffdrv.h", - "freetype/ftchapters.h", - "freetype/ftcid.h", - "freetype/fterrdef.h", - "freetype/fterrors.h", - "freetype/ftfntfmt.h", - "freetype/ftgasp.h", - "freetype/ftglyph.h", - "freetype/ftgxval.h", - "freetype/ftgzip.h", - "freetype/ftimage.h", - "freetype/ftincrem.h", - "freetype/ftlcdfil.h", - "freetype/ftlist.h", - "freetype/ftlzw.h", - "freetype/ftmac.h", - "freetype/ftmm.h", - "freetype/ftmodapi.h", - "freetype/ftmoderr.h", - "freetype/ftotval.h", - "freetype/ftoutln.h", - "freetype/ftpcfdrv.h", - "freetype/ftpfr.h", - "freetype/ftrender.h", - "freetype/ftsizes.h", - "freetype/ftsnames.h", - "freetype/ftstroke.h", - "freetype/ftsynth.h", - "freetype/ftsystem.h", - "freetype/fttrigon.h", - "freetype/ftttdrv.h", - "freetype/fttypes.h", - "freetype/ftwinfnt.h", - "freetype/internal/autohint.h", - "freetype/internal/ftcalc.h", - "freetype/internal/ftdebug.h", - "freetype/internal/ftdriver.h", - "freetype/internal/ftgloadr.h", - "freetype/internal/fthash.h", - "freetype/internal/ftmemory.h", - "freetype/internal/ftobjs.h", - "freetype/internal/ftpic.h", - "freetype/internal/ftrfork.h", - "freetype/internal/ftserv.h", - "freetype/internal/ftstream.h", - "freetype/internal/fttrace.h", - "freetype/internal/ftvalid.h", - "freetype/internal/internal.h", - "freetype/internal/psaux.h", - "freetype/internal/pshints.h", - "freetype/internal/services/svbdf.h", - "freetype/internal/services/svcid.h", - "freetype/internal/services/svfntfmt.h", - "freetype/internal/services/svgldict.h", - "freetype/internal/services/svgxval.h", - "freetype/internal/services/svkern.h", - "freetype/internal/services/svmetric.h", - "freetype/internal/services/svmm.h", - "freetype/internal/services/svotval.h", - "freetype/internal/services/svpfr.h", - "freetype/internal/services/svpostnm.h", - "freetype/internal/services/svprop.h", - "freetype/internal/services/svpscmap.h", - "freetype/internal/services/svpsinfo.h", - "freetype/internal/services/svsfnt.h", - "freetype/internal/services/svttcmap.h", - "freetype/internal/services/svtteng.h", - "freetype/internal/services/svttglyf.h", - "freetype/internal/services/svwinfnt.h", - "freetype/internal/sfnt.h", - "freetype/internal/t1types.h", - "freetype/internal/tttypes.h", - "freetype/t1tables.h", - "freetype/ttnameid.h", - "freetype/tttables.h", - "freetype/tttags.h", - "freetype/ttunpat.h", - "ft2build.h", - ] -} - -source_set("freetype") { - deps = [ - ":freetype_shim", - ] - public_configs = [ ":freetype_config" ] -} - -source_set("bootstrap_freetype_for_harfbuzz") { - deps = [ - ":freetype_shim", - ] - public_configs = [ ":freetype_config" ] +declare_args() { + # Blink needs a recent and properly build-configured FreeType version to + # support OpenType variations, color emoji and avoid security bugs. By default + # we ship and link such a version as part of Chrome. For distributions that + # prefer to keep linking to the version the system, FreeType must be newer + # than version 2.7.1 and have color bitmap support compiled in. WARNING: + # System FreeType configurations other than as described WILL INTRODUCE TEXT + # RENDERING AND SECURITY REGRESSIONS. + use_system_freetype = true }
diff --git a/build/linux/unbundle/replace_gn_files.py b/build/linux/unbundle/replace_gn_files.py index ccd38f8..ce8347a6 100755 --- a/build/linux/unbundle/replace_gn_files.py +++ b/build/linux/unbundle/replace_gn_files.py
@@ -20,7 +20,7 @@ 'ffmpeg': 'third_party/ffmpeg/BUILD.gn', 'flac': 'third_party/flac/BUILD.gn', 'fontconfig': 'third_party/fontconfig/BUILD.gn', - 'freetype': 'third_party/freetype/BUILD.gn', + 'freetype': 'build/config/freetype/freetype.gni', 'harfbuzz-ng': 'third_party/harfbuzz-ng/BUILD.gn', 'icu': 'third_party/icu/BUILD.gn', 'libdrm': 'third_party/libdrm/BUILD.gn',
diff --git a/build/vs_toolchain.py b/build/vs_toolchain.py index 114eefc..0a54e11 100755 --- a/build/vs_toolchain.py +++ b/build/vs_toolchain.py
@@ -340,8 +340,9 @@ to build with.""" env_version = GetVisualStudioVersion() if env_version == '2017': - # VS 2017 Update 3.2 with 10.0.15063.468 SDK and patched setenv.cmd. - return ['a9e1098bba66d2acccc377d5ee81265910f29272'] + # VS 2017 Update 3.2 with 10.0.15063.468 SDK, patched setenv.cmd, and + # 10.0.16299.15 debuggers. + return ['1180cb75833ea365097e279efb2d5d7a42dee4b0'] raise Exception('Unsupported VS version %s' % env_version)
diff --git a/cc/paint/paint_image.h b/cc/paint/paint_image.h index b5da344..5bc445b 100644 --- a/cc/paint/paint_image.h +++ b/cc/paint/paint_image.h
@@ -161,6 +161,9 @@ // Returns the total number of frames known to exist in this image. size_t FrameCount() const; + // Returns an SkImage for the frame at |index|. + sk_sp<SkImage> GetSkImageForFrame(size_t index) const; + std::string ToString() const; private: @@ -179,9 +182,6 @@ void CreateSkImage(); PaintImage MakeSubset(const gfx::Rect& subset) const; - // Returns an SkImage for the frame at |index|. - sk_sp<SkImage> GetSkImageForFrame(size_t index) const; - sk_sp<SkImage> sk_image_; sk_sp<PaintRecord> paint_record_;
diff --git a/cc/raster/gpu_raster_buffer_provider.cc b/cc/raster/gpu_raster_buffer_provider.cc index f1d915e..75694d32 100644 --- a/cc/raster/gpu_raster_buffer_provider.cc +++ b/cc/raster/gpu_raster_buffer_provider.cc
@@ -64,6 +64,27 @@ ri->DeleteTextures(1, &texture_id); } +// The following class is needed to correctly reset GL state when rendering to +// SkCanvases with a GrContext on a RasterInterface enabled context. +class ScopedGrContextAccess { + public: + explicit ScopedGrContextAccess(viz::ContextProvider* context_provider) + : context_provider_(context_provider) { + gpu::raster::RasterInterface* ri = context_provider_->RasterContext(); + ri->BeginGpuRaster(); + + class GrContext* gr_context = context_provider_->GrContext(); + gr_context->resetContext(); + } + ~ScopedGrContextAccess() { + gpu::raster::RasterInterface* ri = context_provider_->RasterContext(); + ri->EndGpuRaster(); + } + + private: + viz::ContextProvider* context_provider_; +}; + static void RasterizeSource( const RasterSource* raster_source, bool resource_has_previous_content, @@ -76,7 +97,7 @@ ResourceProvider::ScopedWriteLockRaster* resource_lock, bool use_distance_field_text, int msaa_sample_count) { - ScopedGpuRaster gpu_raster(context_provider); + ScopedGrContextAccess gr_context_access(context_provider); gpu::raster::RasterInterface* ri = context_provider->RasterContext(); GLuint texture_id = resource_lock->ConsumeTexture(ri);
diff --git a/cc/raster/raster_buffer_provider_perftest.cc b/cc/raster/raster_buffer_provider_perftest.cc index a95457e4..7877a52 100644 --- a/cc/raster/raster_buffer_provider_perftest.cc +++ b/cc/raster/raster_buffer_provider_perftest.cc
@@ -71,11 +71,10 @@ if (pname == GL_QUERY_RESULT_AVAILABLE_EXT) *params = 1; } - void GenUnverifiedSyncTokenCHROMIUM(GLuint64 fence_sync, - GLbyte* sync_token) override { + void GenUnverifiedSyncTokenCHROMIUM(GLbyte* sync_token) override { // Copy the data over after setting the data to ensure alignment. gpu::SyncToken sync_token_data(gpu::CommandBufferNamespace::GPU_IO, 0, - gpu::CommandBufferId(), fence_sync); + gpu::CommandBufferId(), 0); memcpy(sync_token, &sync_token_data, sizeof(sync_token_data)); } };
diff --git a/cc/resources/display_resource_provider.cc b/cc/resources/display_resource_provider.cc index 04209ae..b4df9e74 100644 --- a/cc/resources/display_resource_provider.cc +++ b/cc/resources/display_resource_provider.cc
@@ -254,9 +254,7 @@ if (!need_synchronization_resources.empty()) { DCHECK(child_info->needs_sync_tokens); DCHECK(gl); - const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM(); - gl->OrderingBarrierCHROMIUM(); - gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, new_sync_token.GetData()); + gl->GenUnverifiedSyncTokenCHROMIUM(new_sync_token.GetData()); unverified_sync_tokens.push_back(new_sync_token.GetData()); }
diff --git a/cc/resources/layer_tree_resource_provider.cc b/cc/resources/layer_tree_resource_provider.cc index 788560d3..69a5a82b 100644 --- a/cc/resources/layer_tree_resource_provider.cc +++ b/cc/resources/layer_tree_resource_provider.cc
@@ -134,9 +134,7 @@ if (!need_synchronization_resources.empty()) { DCHECK(settings_.delegated_sync_points_required); DCHECK(gl); - const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM(); - gl->OrderingBarrierCHROMIUM(); - gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, new_sync_token.GetData()); + gl->GenUnverifiedSyncTokenCHROMIUM(new_sync_token.GetData()); unverified_sync_tokens.push_back(new_sync_token.GetData()); }
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc index 7f9e545..4eaf66238 100644 --- a/cc/resources/resource_provider.cc +++ b/cc/resources/resource_provider.cc
@@ -1036,36 +1036,20 @@ gpu::SyncToken ResourceProvider::GenerateSyncTokenHelper( gpu::gles2::GLES2Interface* gl) { DCHECK(gl); - const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM(); - - // Barrier to sync worker context output to cc context. - gl->OrderingBarrierCHROMIUM(); - - // Generate sync token after the barrier for cross context synchronization. gpu::SyncToken sync_token; - gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); - + gl->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); DCHECK(sync_token.HasData() || gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR); - return sync_token; } gpu::SyncToken ResourceProvider::GenerateSyncTokenHelper( gpu::raster::RasterInterface* ri) { DCHECK(ri); - const uint64_t fence_sync = ri->InsertFenceSyncCHROMIUM(); - - // Barrier to sync worker context output to cc context. - ri->OrderingBarrierCHROMIUM(); - - // Generate sync token after the barrier for cross context synchronization. gpu::SyncToken sync_token; - ri->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); - + ri->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); DCHECK(sync_token.HasData() || ri->GetGraphicsResetStatusKHR() != GL_NO_ERROR); - return sync_token; }
diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc index 4f22efb..9adc6a6 100644 --- a/cc/resources/resource_provider_unittest.cc +++ b/cc/resources/resource_provider_unittest.cc
@@ -121,12 +121,10 @@ void RetireTextureId(GLuint) override {} - GLuint64 insertFenceSync() override { return next_fence_sync_++; } - - void genSyncToken(GLuint64 fence_sync, GLbyte* sync_token) override { + void genSyncToken(GLbyte* sync_token) override { gpu::SyncToken sync_token_data(gpu::CommandBufferNamespace::GPU_IO, 0, gpu::CommandBufferId::FromUnsafeValue(0x123), - fence_sync); + next_fence_sync_++); sync_token_data.SetVerifyFlush(); memcpy(sync_token, &sync_token_data, sizeof(sync_token_data)); } @@ -198,11 +196,8 @@ return base::WrapUnique(new ResourceProviderContext(shared_data)); } - GLuint64 insertFenceSync() override { - return shared_data_->InsertFenceSync(); - } - - void genSyncToken(GLuint64 fence_sync, GLbyte* sync_token) override { + void genSyncToken(GLbyte* sync_token) override { + uint64_t fence_sync = shared_data_->InsertFenceSync(); gpu::SyncToken sync_token_data(gpu::CommandBufferNamespace::GPU_IO, 0, gpu::CommandBufferId::FromUnsafeValue(0x123), fence_sync); @@ -485,8 +480,7 @@ gpu::Mailbox gpu_mailbox; child_context_->genMailboxCHROMIUM(gpu_mailbox.name); child_context_->produceTextureDirectCHROMIUM(texture, gpu_mailbox.name); - child_context_->genSyncToken(child_context_->insertFenceSync(), - sync_token->GetData()); + child_context_->genSyncToken(sync_token->GetData()); EXPECT_TRUE(sync_token->HasData()); std::unique_ptr<viz::SharedBitmap> shared_bitmap; @@ -867,8 +861,7 @@ child_context_->produceTextureDirectCHROMIUM(external_texture_id, external_mailbox.name); gpu::SyncToken external_sync_token; - child_context_->genSyncToken(child_context_->insertFenceSync(), - external_sync_token.GetData()); + child_context_->genSyncToken(external_sync_token.GetData()); EXPECT_TRUE(external_sync_token.HasData()); viz::TransferableResource id1_transfer = @@ -995,8 +988,7 @@ child_context_->produceTextureDirectCHROMIUM(external_texture_id, external_mailbox.name); gpu::SyncToken external_sync_token; - child_context_->genSyncToken(child_context_->insertFenceSync(), - external_sync_token.GetData()); + child_context_->genSyncToken(external_sync_token.GetData()); EXPECT_TRUE(external_sync_token.HasData()); viz::ResourceId id3 = child_resource_provider_->ImportResource( viz::TransferableResource::MakeGL(external_mailbox, GL_LINEAR, @@ -1978,7 +1970,7 @@ context()->genMailboxCHROMIUM(mailbox.name); context()->produceTextureDirectCHROMIUM(texture, mailbox.name); gpu::SyncToken sync_token; - context()->genSyncToken(context()->insertFenceSync(), sync_token.GetData()); + context()->genSyncToken(sync_token.GetData()); EXPECT_TRUE(sync_token.HasData()); // All the logic below assumes that the sync token releases are all positive. @@ -2019,8 +2011,7 @@ context()->produceTextureDirectCHROMIUM(other_texture, mailbox.name); context()->deleteTexture(other_texture); - context()->genSyncToken(context()->insertFenceSync(), - list[0].mailbox_holder.sync_token.GetData()); + context()->genSyncToken(list[0].mailbox_holder.sync_token.GetData()); EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); // Receive the resource, then delete it, expect the sync points to be @@ -2074,8 +2065,7 @@ context()->produceTextureDirectCHROMIUM(other_texture, mailbox.name); context()->deleteTexture(other_texture); - context()->genSyncToken(context()->insertFenceSync(), - list[0].mailbox_holder.sync_token.GetData()); + context()->genSyncToken(list[0].mailbox_holder.sync_token.GetData()); EXPECT_TRUE(list[0].mailbox_holder.sync_token.HasData()); // Delete the resource, which shouldn't do anything.
diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc index 4d01b50..dd71b9b 100644 --- a/cc/resources/video_resource_updater.cc +++ b/cc/resources/video_resource_updater.cc
@@ -99,7 +99,6 @@ case media::PIXEL_FORMAT_YUV444P12: case media::PIXEL_FORMAT_Y8: case media::PIXEL_FORMAT_Y16: - case media::PIXEL_FORMAT_I422: case media::PIXEL_FORMAT_UNKNOWN: break; } @@ -116,9 +115,7 @@ if (sync_token_.HasData()) { *sync_token = sync_token_; } else { - const uint64_t fence_sync = gl_->InsertFenceSyncCHROMIUM(); - gl_->ShallowFlushCHROMIUM(); - gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token->GetData()); + gl_->GenSyncTokenCHROMIUM(sync_token->GetData()); } } @@ -141,9 +138,7 @@ // Sync tokens passed downstream to the compositor can be unverified. void GenerateCompositorSyncToken(gpu::gles2::GLES2Interface* gl, gpu::SyncToken* sync_token) { - const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM(); - gl->OrderingBarrierCHROMIUM(); - gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token->GetData()); + gl->GenUnverifiedSyncTokenCHROMIUM(sync_token->GetData()); } } // namespace
diff --git a/cc/test/test_gles2_interface.cc b/cc/test/test_gles2_interface.cc index 1ff09cc..9766c226 100644 --- a/cc/test/test_gles2_interface.cc +++ b/cc/test/test_gles2_interface.cc
@@ -308,18 +308,12 @@ test_context_->bufferData(target, size, data, usage); } -GLuint64 TestGLES2Interface::InsertFenceSyncCHROMIUM() { - return test_context_->insertFenceSync(); +void TestGLES2Interface::GenSyncTokenCHROMIUM(GLbyte* sync_token) { + test_context_->genSyncToken(sync_token); } -void TestGLES2Interface::GenSyncTokenCHROMIUM(GLuint64 fence_sync, - GLbyte* sync_token) { - test_context_->genSyncToken(fence_sync, sync_token); -} - -void TestGLES2Interface::GenUnverifiedSyncTokenCHROMIUM(GLuint64 fence_sync, - GLbyte* sync_token) { - test_context_->genSyncToken(fence_sync, sync_token); +void TestGLES2Interface::GenUnverifiedSyncTokenCHROMIUM(GLbyte* sync_token) { + test_context_->genSyncToken(sync_token); } void TestGLES2Interface::VerifySyncTokensCHROMIUM(GLbyte** sync_tokens,
diff --git a/cc/test/test_gles2_interface.h b/cc/test/test_gles2_interface.h index 7231d19..93e068f 100644 --- a/cc/test/test_gles2_interface.h +++ b/cc/test/test_gles2_interface.h
@@ -133,10 +133,8 @@ const void* data, GLenum usage) override; - GLuint64 InsertFenceSyncCHROMIUM() override; - void GenSyncTokenCHROMIUM(GLuint64 fence_sync, GLbyte* sync_token) override; - void GenUnverifiedSyncTokenCHROMIUM(GLuint64 fence_sync, - GLbyte* sync_token) override; + void GenSyncTokenCHROMIUM(GLbyte* sync_token) override; + void GenUnverifiedSyncTokenCHROMIUM(GLbyte* sync_token) override; void VerifySyncTokensCHROMIUM(GLbyte** sync_tokens, GLsizei count) override; void WaitSyncTokenCHROMIUM(const GLbyte* sync_token) override;
diff --git a/cc/test/test_web_graphics_context_3d.cc b/cc/test/test_web_graphics_context_3d.cc index db85788..a55b1b1 100644 --- a/cc/test/test_web_graphics_context_3d.cc +++ b/cc/test/test_web_graphics_context_3d.cc
@@ -643,18 +643,14 @@ return image_id; } -GLuint64 TestWebGraphicsContext3D::insertFenceSync() { - return next_insert_fence_sync_++; -} - -void TestWebGraphicsContext3D::genSyncToken(GLuint64 fence_sync, - GLbyte* sync_token) { +void TestWebGraphicsContext3D::genSyncToken(GLbyte* sync_token) { // Don't return a valid sync token if context is lost. This matches behavior // of CommandBufferProxyImpl. if (context_lost_) return; gpu::SyncToken sync_token_data(gpu::CommandBufferNamespace::GPU_IO, 0, - gpu::CommandBufferId(), fence_sync); + gpu::CommandBufferId(), + next_insert_fence_sync_++); sync_token_data.SetVerifyFlush(); memcpy(sync_token, &sync_token_data, sizeof(sync_token_data)); }
diff --git a/cc/test/test_web_graphics_context_3d.h b/cc/test/test_web_graphics_context_3d.h index f0286c5..06e020aa 100644 --- a/cc/test/test_web_graphics_context_3d.h +++ b/cc/test/test_web_graphics_context_3d.h
@@ -267,8 +267,7 @@ GLenum internalformat, GLenum usage); - virtual GLuint64 insertFenceSync(); - virtual void genSyncToken(GLuint64 fence_sync, GLbyte* sync_token); + virtual void genSyncToken(GLbyte* sync_token); virtual void waitSyncToken(const GLbyte* sync_token); virtual void verifySyncTokens(GLbyte** sync_tokens, GLsizei count);
diff --git a/cc/tiles/gpu_image_decode_cache.cc b/cc/tiles/gpu_image_decode_cache.cc index 85c647e..f7721fe0 100644 --- a/cc/tiles/gpu_image_decode_cache.cc +++ b/cc/tiles/gpu_image_decode_cache.cc
@@ -126,61 +126,36 @@ } // Draws and scales the provided |draw_image| into the |target_pixmap|. If the -// draw/scale can be done directly, calls directly into PaintImage::Decode. +// draw/scale can be done directly, calls directly into SkImage::scalePixels, // if not, decodes to a compatible temporary pixmap and then converts that into // the |target_pixmap|. bool DrawAndScaleImage(const DrawImage& draw_image, SkPixmap* target_pixmap) { - // We don't want to perform any color conversion here, so create a new pixmap - // with a null colorspace that shares |target_pixmap|'s memory. - SkPixmap pixmap(target_pixmap->info().makeColorSpace(nullptr), - target_pixmap->writable_addr(), target_pixmap->rowBytes()); - - const PaintImage& paint_image = draw_image.paint_image(); - SkISize supported_size = - paint_image.GetSupportedDecodeSize(pixmap.bounds().size()); - - if (supported_size == pixmap.bounds().size()) { - SkImageInfo info = pixmap.info(); - return paint_image.Decode(pixmap.writable_addr(), &info, nullptr, - draw_image.frame_index()); + sk_sp<SkImage> image = + draw_image.paint_image().GetSkImageForFrame(draw_image.frame_index()); + if (image->dimensions() == target_pixmap->bounds().size() || + target_pixmap->info().colorType() == kN32_SkColorType) { + // If no scaling is occurring, or if the target colortype is already N32, + // just scale directly. + return image->scalePixels(*target_pixmap, + CalculateDesiredFilterQuality(draw_image), + SkImage::kDisallow_CachingHint); } - // If we can't decode/scale directly, we will handle this in up to 3 steps. - // Step 1: Decode at the nearest (larger) directly supported size. - SkImageInfo decode_info = SkImageInfo::MakeN32Premul(supported_size.width(), - supported_size.height()); + // If the target colortype is not N32, it may be impossible to scale + // directly. Instead scale into an N32 pixmap, and convert that into the + // |target_pixmap|. + SkImageInfo decode_info = + target_pixmap->info().makeColorType(kN32_SkColorType); SkBitmap decode_bitmap; if (!decode_bitmap.tryAllocPixels(decode_info)) return false; SkPixmap decode_pixmap(decode_bitmap.info(), decode_bitmap.getPixels(), decode_bitmap.rowBytes()); - if (!paint_image.Decode(decode_pixmap.writable_addr(), &decode_info, nullptr, - draw_image.frame_index())) { + if (!image->scalePixels(decode_pixmap, + CalculateDesiredFilterQuality(draw_image), + SkImage::kDisallow_CachingHint)) return false; - } - - // Step 2a: Scale to |pixmap| directly if kN32_SkColorType. - if (pixmap.info().colorType() == kN32_SkColorType) { - return decode_pixmap.scalePixels(pixmap, - CalculateDesiredFilterQuality(draw_image)); - } - - // Step 2b: Scale to temporary pixmap of kN32_SkColorType. - SkImageInfo scaled_info = pixmap.info().makeColorType(kN32_SkColorType); - SkBitmap scaled_bitmap; - if (!scaled_bitmap.tryAllocPixels(scaled_info)) - return false; - SkPixmap scaled_pixmap(scaled_bitmap.info(), scaled_bitmap.getPixels(), - scaled_bitmap.rowBytes()); - if (!decode_pixmap.scalePixels(scaled_pixmap, - CalculateDesiredFilterQuality(draw_image))) { - return false; - } - - // Step 3: Copy the temporary scaled pixmap to |pixmap|, performing - // color type conversion. We can't do the color conversion in step 1, as - // the scale in step 2 must happen in kN32_SkColorType. - return scaled_pixmap.readPixels(pixmap); + return decode_pixmap.readPixels(*target_pixmap); } // Returns the GL texture ID backing the given SkImage. @@ -408,23 +383,16 @@ void GpuImageDecodeCache::DecodedImageData::SetLockedData( std::unique_ptr<base::DiscardableMemory> data, - sk_sp<SkImage> image, bool out_of_raster) { DCHECK(data); DCHECK(!data_); - DCHECK(image); - DCHECK(!image_); data_ = std::move(data); - image_ = std::move(image); OnSetLockedData(out_of_raster); } void GpuImageDecodeCache::DecodedImageData::ResetData() { - if (data_) { - DCHECK(image_); + if (data_) ReportUsageStats(); - } - image_ = nullptr; data_ = nullptr; OnResetData(); } @@ -476,13 +444,11 @@ DecodedDataMode mode, size_t size, const gfx::ColorSpace& target_color_space, - SkFilterQuality quality, - int mip_level) + const SkImage::DeferredTextureImageUsageParams& upload_params) : mode(mode), size(size), target_color_space(target_color_space), - quality(quality), - mip_level(mip_level) {} + upload_params(upload_params) {} GpuImageDecodeCache::ImageData::~ImageData() { // We should never delete ImageData while it is in use or before it has been @@ -502,11 +468,12 @@ context_(context), persistent_cache_(PersistentCache::NO_AUTO_EVICT), max_working_set_bytes_(max_working_set_bytes) { - // Acquire the context_lock so that we can safely retrieve - // |max_texture_size_|. + // Acquire the context_lock so that we can safely retrieve the + // GrContextThreadSafeProxy. This proxy can then be used with no lock held. { viz::ContextProvider::ScopedContextLock context_lock(context_); - max_texture_size_ = context_->GrContext()->caps()->maxTextureSize(); + context_threadsafe_proxy_ = sk_sp<GrContextThreadSafeProxy>( + context_->GrContext()->threadSafeProxy()); } // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview). @@ -686,8 +653,8 @@ image_data->upload.mark_used(); DCHECK(image || image_data->decode.decode_failure); - SkSize scale_factor = - CalculateScaleFactorForMipLevel(draw_image, image_data->mip_level); + SkSize scale_factor = CalculateScaleFactorForMipLevel( + draw_image, image_data->upload_params.fPreScaleMipLevel); DecodedDrawImage decoded_draw_image( std::move(image), SkSize(), scale_factor, CalculateDesiredFilterQuality(draw_image)); @@ -1230,43 +1197,65 @@ } TRACE_EVENT0("cc", "GpuImageDecodeCache::DecodeImage"); - RecordImageMipLevelUMA(image_data->mip_level); + RecordImageMipLevelUMA(image_data->upload_params.fPreScaleMipLevel); image_data->decode.ResetData(); std::unique_ptr<base::DiscardableMemory> backing_memory; - sk_sp<SkImage> image; { base::AutoUnlock unlock(lock_); + backing_memory = base::DiscardableMemoryAllocator::GetInstance() ->AllocateLockedDiscardableMemory(image_data->size); - SkImageInfo image_info = - CreateImageInfoForDrawImage(draw_image, image_data->mip_level); - SkPixmap pixmap(image_info, backing_memory->data(), - image_info.minRowBytes()); - if (!DrawAndScaleImage(draw_image, &pixmap)) { - DLOG(ERROR) << "DrawAndScaleImage failed."; - backing_memory->Unlock(); - backing_memory.reset(); - } else { - image = - SkImage::MakeFromRaster(pixmap, [](const void*, void*) {}, nullptr); + + switch (image_data->mode) { + case DecodedDataMode::CPU: { + SkImageInfo image_info = CreateImageInfoForDrawImage( + draw_image, image_data->upload_params.fPreScaleMipLevel); + // In order to match GPU scaling quality (which uses mip-maps at high + // quality), we want to use at most medium filter quality for the + // scale. + SkPixmap image_pixmap(image_info.makeColorSpace(nullptr), + backing_memory->data(), image_info.minRowBytes()); + // Note that scalePixels falls back to readPixels if the scale is 1x, so + // no need to special case that as an optimization. + if (!DrawAndScaleImage(draw_image, &image_pixmap)) { + DLOG(ERROR) << "scalePixels failed."; + backing_memory->Unlock(); + backing_memory.reset(); + } + break; + } + case DecodedDataMode::GPU: { + // TODO(crbug.com/649167): Params should not have changed since initial + // sizing. Somehow this still happens. We should investigate and re-add + // DCHECKs here to enforce this. + sk_sp<SkImage> image = draw_image.paint_image().GetSkImageForFrame( + draw_image.frame_index()); + if (!image->getDeferredTextureImageData( + *context_threadsafe_proxy_.get(), &image_data->upload_params, 1, + backing_memory->data(), nullptr, color_type_)) { + DLOG(ERROR) << "getDeferredTextureImageData failed despite params " + << "having validated."; + backing_memory->Unlock(); + backing_memory.reset(); + } + break; + } } } if (image_data->decode.data()) { - DCHECK(image_data->decode.image()); // An at-raster task decoded this before us. Ingore our decode. return; } if (!backing_memory) { - DCHECK(!image); // If |backing_memory| was not populated, we had a non-decodable image. image_data->decode.decode_failure = true; return; } - image_data->decode.SetLockedData(std::move(backing_memory), std::move(image), + image_data->decode.SetLockedData(std::move(backing_memory), task_type == TaskType::kOutOfRaster); } @@ -1296,11 +1285,26 @@ DCHECK_GT(image_data->decode.ref_count, 0u); DCHECK_GT(image_data->upload.ref_count, 0u); - sk_sp<SkImage> uploaded_image = image_data->decode.image(); - if (image_data->mode == DecodedDataMode::GPU) { + sk_sp<SkImage> uploaded_image; + { base::AutoUnlock unlock(lock_); - uploaded_image = - uploaded_image->makeTextureImage(context_->GrContext(), nullptr); + switch (image_data->mode) { + case DecodedDataMode::CPU: { + SkImageInfo image_info = CreateImageInfoForDrawImage( + draw_image, image_data->upload_params.fPreScaleMipLevel); + SkPixmap pixmap(image_info, image_data->decode.data()->data(), + image_info.minRowBytes()); + uploaded_image = + SkImage::MakeFromRaster(pixmap, [](const void*, void*) {}, nullptr); + break; + } + case DecodedDataMode::GPU: { + uploaded_image = SkImage::MakeFromDeferredTextureImageData( + context_->GrContext(), image_data->decode.data()->data(), + SkBudgeted::kNo); + break; + } + } } image_data->decode.mark_used(); @@ -1345,22 +1349,30 @@ "GpuImageDecodeCache::CreateImageData"); lock_.AssertAcquired(); - int mip_level = CalculateUploadScaleMipLevel(draw_image); - SkImageInfo image_info = CreateImageInfoForDrawImage(draw_image, mip_level); - DecodedDataMode mode; - if (image_info.width() > max_texture_size_ || - image_info.height() > max_texture_size_) { - // Image too large to upload. Try to use SW fallback. + int upload_scale_mip_level = CalculateUploadScaleMipLevel(draw_image); + // TODO(ericrk): Remove the matrix parameter in this call. + auto params = SkImage::DeferredTextureImageUsageParams( + SkMatrix::I(), CalculateDesiredFilterQuality(draw_image), + upload_scale_mip_level); + sk_sp<SkImage> image = + draw_image.paint_image().GetSkImageForFrame(draw_image.frame_index()); + size_t data_size = image->getDeferredTextureImageData( + *context_threadsafe_proxy_.get(), ¶ms, 1, nullptr, nullptr, + color_type_); + + if (data_size == 0) { + // Can't upload image, too large or other failure. Try to use SW fallback. + SkImageInfo image_info = + CreateImageInfoForDrawImage(draw_image, upload_scale_mip_level); + data_size = image_info.computeMinByteSize(); mode = DecodedDataMode::CPU; } else { mode = DecodedDataMode::GPU; } - size_t data_size = image_info.computeMinByteSize(); - return base::WrapRefCounted( - new ImageData(mode, data_size, draw_image.target_color_space(), - CalculateDesiredFilterQuality(draw_image), mip_level)); + return base::MakeRefCounted<ImageData>( + mode, data_size, draw_image.target_color_space(), params); } void GpuImageDecodeCache::DeleteImage(ImageData* image_data) { @@ -1417,7 +1429,7 @@ CalculateSizeForMipLevel(draw_image, upload_scale_mip_level); return SkImageInfo::Make(mip_size.width(), mip_size.height(), color_type_, kPremul_SkAlphaType, - sk_ref_sp(draw_image.paint_image().color_space())); + draw_image.target_color_space().ToSkColorSpace()); } bool GpuImageDecodeCache::TryLockImage(HaveContextLock have_context_lock, @@ -1490,11 +1502,11 @@ // the provided |draw_image|. bool GpuImageDecodeCache::IsCompatible(const ImageData* image_data, const DrawImage& draw_image) const { - bool is_scaled = image_data->mip_level != 0; - bool scale_is_compatible = - CalculateUploadScaleMipLevel(draw_image) >= image_data->mip_level; - bool quality_is_compatible = - CalculateDesiredFilterQuality(draw_image) <= image_data->quality; + bool is_scaled = image_data->upload_params.fPreScaleMipLevel != 0; + bool scale_is_compatible = CalculateUploadScaleMipLevel(draw_image) >= + image_data->upload_params.fPreScaleMipLevel; + bool quality_is_compatible = CalculateDesiredFilterQuality(draw_image) <= + image_data->upload_params.fQuality; bool color_is_compatible = image_data->target_color_space == draw_image.target_color_space(); if (!color_is_compatible)
diff --git a/cc/tiles/gpu_image_decode_cache.h b/cc/tiles/gpu_image_decode_cache.h index d41bd2d..dafc5ab 100644 --- a/cc/tiles/gpu_image_decode_cache.h +++ b/cc/tiles/gpu_image_decode_cache.h
@@ -203,14 +203,9 @@ void Unlock(); void SetLockedData(std::unique_ptr<base::DiscardableMemory> data, - sk_sp<SkImage> image, bool out_of_raster); void ResetData(); base::DiscardableMemory* data() const { return data_.get(); } - sk_sp<SkImage> image() const { - DCHECK(is_locked()); - return image_; - } bool decode_failure = false; // Similar to |task|, but only is generated if there is no associated upload @@ -221,7 +216,6 @@ void ReportUsageStats() const; std::unique_ptr<base::DiscardableMemory> data_; - sk_sp<SkImage> image_; }; // Stores the GPU-side image and supporting fields. @@ -249,15 +243,13 @@ ImageData(DecodedDataMode mode, size_t size, const gfx::ColorSpace& target_color_space, - SkFilterQuality quality, - int mip_level); + const SkImage::DeferredTextureImageUsageParams& upload_params); const DecodedDataMode mode; const size_t size; gfx::ColorSpace target_color_space; - SkFilterQuality quality; - int mip_level; bool is_at_raster = false; + SkImage::DeferredTextureImageUsageParams upload_params; // If true, this image is no longer in our |persistent_cache_| and will be // deleted as soon as its ref count reaches zero. @@ -381,7 +373,7 @@ const SkColorType color_type_; viz::ContextProvider* context_; - int max_texture_size_ = 0; + sk_sp<GrContextThreadSafeProxy> context_threadsafe_proxy_; // All members below this point must only be accessed while holding |lock_|. // The exception are const members like |normal_max_cache_bytes_| that can
diff --git a/cc/trees/layer_tree_host_unittest_context.cc b/cc/trees/layer_tree_host_unittest_context.cc index 2139ddf..aa950bb 100644 --- a/cc/trees/layer_tree_host_unittest_context.cc +++ b/cc/trees/layer_tree_host_unittest_context.cc
@@ -898,11 +898,8 @@ gpu::Mailbox mailbox; gl->GenMailboxCHROMIUM(mailbox.name); - const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM(); - gl->ShallowFlushCHROMIUM(); - gpu::SyncToken sync_token; - gl->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + gl->GenSyncTokenCHROMIUM(sync_token.GetData()); scoped_refptr<Layer> root = Layer::Create(); root->SetBounds(gfx::Size(10, 10));
diff --git a/cc/trees/layer_tree_host_unittest_copyrequest.cc b/cc/trees/layer_tree_host_unittest_copyrequest.cc index 4574bd8d..16da098 100644 --- a/cc/trees/layer_tree_host_unittest_copyrequest.cc +++ b/cc/trees/layer_tree_host_unittest_copyrequest.cc
@@ -1052,9 +1052,7 @@ gpu::Mailbox mailbox; gl->GenMailboxCHROMIUM(mailbox.name); - const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM(); - gl->ShallowFlushCHROMIUM(); - gl->GenSyncTokenCHROMIUM(fence_sync, sync_token_.GetData()); + gl->GenSyncTokenCHROMIUM(sync_token_.GetData()); request->SetMailbox(mailbox, sync_token_); EXPECT_TRUE(request->has_mailbox());
diff --git a/chrome/VERSION b/chrome/VERSION index adb50f6..a5b163d 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=65 MINOR=0 -BUILD=3296 +BUILD=3299 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java index 0a2bea34e..8455dd4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.bookmarks; +import android.os.SystemClock; import android.text.TextUtils; import android.util.Pair; @@ -11,6 +12,7 @@ import org.chromium.base.ObserverList; import org.chromium.base.VisibleForTesting; import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.browser.partnerbookmarks.PartnerBookmarksShim; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.components.bookmarks.BookmarkId; @@ -19,6 +21,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeUnit; /** * Provides the communication channel for Android to fetch and manipulate the @@ -303,10 +306,13 @@ return true; } + long startTime = SystemClock.elapsedRealtime(); addObserver(new BookmarkModelObserver() { @Override public void bookmarkModelLoaded() { removeObserver(this); + RecordHistogram.recordTimesHistogram("PartnerBookmark.LoadingTime", + SystemClock.elapsedRealtime() - startTime, TimeUnit.MILLISECONDS); runAfterModelLoaded.run(); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java index a207ff9..53529a8c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java
@@ -60,6 +60,7 @@ private Context mContext; private BookmarkPromoHeader mPromoHeaderManager; private String mSearchText; + private BookmarkId mCurrentFolder; private BookmarkModelObserver mBookmarkModelObserver = new BookmarkModelObserver() { @Override @@ -310,6 +311,7 @@ assert mDelegate != null; mSearchText = EMPTY_QUERY; + mCurrentFolder = folder; if (folder.equals(mDelegate.getModel().getRootFolderId())) { setBookmarks(mTopLevelFolders, new ArrayList<BookmarkId>()); @@ -328,6 +330,14 @@ public void onSelectionStateChange(List<BookmarkId> selectedBookmarks) {} /** + * Refresh the list of bookmarks within the currently visible folder. + */ + public void refresh() { + if (mCurrentFolder == null) return; + onFolderStateSet(mCurrentFolder); + } + + /** * Synchronously searches for the given query. * @param query The query text to search for. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java index f666b3f..dacb0c1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java
@@ -23,6 +23,7 @@ import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver; import org.chromium.chrome.browser.favicon.LargeIconBridge; +import org.chromium.chrome.browser.partnerbookmarks.PartnerBookmarksReader; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.snackbar.SnackbarManager; import org.chromium.chrome.browser.util.FeatureUtilities; @@ -41,7 +42,8 @@ * {@link BookmarkActivity} (phone) and {@link BookmarkPage} (tablet). */ public class BookmarkManager implements BookmarkDelegate, SearchDelegate, - SelectableBottomSheetContentManager<BookmarkId> { + SelectableBottomSheetContentManager<BookmarkId>, + PartnerBookmarksReader.FaviconUpdateObserver { private static final int FAVICON_MAX_CACHE_SIZE_BYTES = 10 * 1024 * 1024; // 10MB /** @@ -66,6 +68,7 @@ private SelectionDelegate<BookmarkId> mSelectionDelegate; private final Stack<BookmarkUIState> mStateStack = new Stack<>(); private LargeIconBridge mLargeIconBridge; + private boolean mFaviconsNeedRefresh; private String mInitialUrl; private boolean mIsDialogUi; private boolean mIsDestroyed; @@ -117,6 +120,8 @@ mActivity = activity; mIsDialogUi = isDialogUi; + PartnerBookmarksReader.addFaviconUpdateObserver(this); + mSelectionDelegate = new SelectionDelegate<BookmarkId>() { @Override public boolean toggleSelectionForItem(BookmarkId bookmark) { @@ -183,6 +188,20 @@ ContextUtils.getAppSharedPreferences().edit().remove(PREF_SEARCH_HISTORY).apply(); } + @Override + public void onUpdateFavicon(String url) { + mLargeIconBridge.clearFavicon(url); + mFaviconsNeedRefresh = true; + } + + @Override + public void onCompletedFaviconLoading() { + if (mFaviconsNeedRefresh) { + mAdapter.refresh(); + mFaviconsNeedRefresh = false; + } + } + /** * Destroys and cleans up itself. This must be called after done using this class. */ @@ -206,6 +225,7 @@ mBookmarkModel = null; mLargeIconBridge.destroy(); mLargeIconBridge = null; + PartnerBookmarksReader.removeFaviconUpdateObserver(this); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java index 64be54d..89900ed 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
@@ -611,14 +611,15 @@ * the screen, in pixels. */ public Rect getPanelRect() { - Rect visibleDisplayFrame = new Rect(); - mActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(visibleDisplayFrame); + int[] contentLocationInWindow = new int[2]; + mActivity.findViewById(android.R.id.content).getLocationInWindow(contentLocationInWindow); + int leftPadding = contentLocationInWindow[0]; + int topPadding = contentLocationInWindow[1]; // getOffsetX() and getOffsetY() return the position of the panel relative to the activity, - // therefore visibleDisplayFrame.left and visibleDisplayFrame.top are added to get the - // position in the screen. - int left = (int) (getOffsetX() / mPxToDp) + visibleDisplayFrame.left; - int top = (int) ((getOffsetY()) / mPxToDp) + visibleDisplayFrame.top; + // therefore leftPadding and topPadding are added to get the position in the screen. + int left = (int) (getOffsetX() / mPxToDp) + leftPadding; + int top = (int) (getOffsetY() / mPxToDp) + topPadding; int bottom = top + (int) (getBarHeight() / mPxToDp); int right = left + (int) (getWidth() / mPxToDp);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java index 4dc69f3..cf3d9ee 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
@@ -834,6 +834,7 @@ */ public void onAccessibilityModeChanged(boolean enabled) { mIsAccessibilityModeEnabled = enabled; + if (enabled) hideContextualSearch(StateChangeReason.UNKNOWN); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/favicon/LargeIconBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/favicon/LargeIconBridge.java index 36c41fedc..4d0d31e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/favicon/LargeIconBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/favicon/LargeIconBridge.java
@@ -150,6 +150,13 @@ } } + /** + * Removes the favicon from the local cache for the given URL. + */ + public void clearFavicon(String url) { + mFaviconCache.remove(url); + } + private static native long nativeInit(); private static native void nativeDestroy(long nativeLargeIconBridge); private static native boolean nativeGetLargeIconForURL(long nativeLargeIconBridge,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottle.java b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottle.java index 1d972eaf..d6443eca 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottle.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottle.java
@@ -86,7 +86,7 @@ if (result == FaviconFetchResult.FAILURE_SERVER_ERROR) { mNewEntries.put(url, System.currentTimeMillis() + FAVICON_RETRIEVAL_TIMEOUT_MS); - } else if (result != FaviconFetchResult.SUCCESS && !shouldFetchFromServerIfNecessary(url) + } else if (!isSuccessfulFetchResult(result) && !shouldFetchFromServerIfNecessary(url) && (System.currentTimeMillis() < mCurrentEntries.get(url))) { // Keep storing an entry if it hasn't yet expired and we get didn't just get a success // response. @@ -94,6 +94,11 @@ } } + private boolean isSuccessfulFetchResult(@FaviconFetchResult int result) { + return result == FaviconFetchResult.SUCCESS_FROM_CACHE + || result == FaviconFetchResult.SUCCESS_FROM_SERVER; + } + /** * Determines, based on the contents of our entry set, whether or not we should even attempt to * reach out to a server to retrieve a favicon that isn't currently in our favicon image cache.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java index 95fd317..86c8321 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java
@@ -16,6 +16,7 @@ import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.Set; import javax.annotation.concurrent.GuardedBy; @@ -24,6 +25,7 @@ */ public class PartnerBookmarksReader { private static final String TAG = "PartnerBMReader"; + private static Set<FaviconUpdateObserver> sFaviconUpdateObservers = new HashSet<>(); static final String LAST_EMPTY_READ_PREFS_NAME = "PartnerBookmarksReader.last_empty_read"; @@ -50,12 +52,31 @@ // don't end up shutting the bookmark reader down prematurely. private final Object mProgressLock = new Object(); @GuardedBy("mProgressLock") - private int mNumFaviconsInProgress = 0; + private int mNumFaviconsInProgress; @GuardedBy("mProgressLock") - private boolean mShutDown = false; + private boolean mShutDown; + @GuardedBy("mProgressLock") + private boolean mFaviconsFetchedFromServer; private boolean mFinishedReading; /** + * Observer for listeners to receive updates when changes are made to the favicon cache. + */ + public interface FaviconUpdateObserver { + /** + * Called when a favicon has been updated, so observers can update their view if necessary. + * + * @param url The URL of the page for the favicon being updated. + */ + void onUpdateFavicon(String url); + + /** + * Called when all favicon loading for the partner bookmarks has completed. + */ + void onCompletedFaviconLoading(); + } + + /** * A callback used to indicate success or failure of favicon fetching when retrieving favicons * from cache or server. */ @@ -78,6 +99,26 @@ } /** + * Adds an observer for favicon updates as a result of fetching favicons from server during + * partner bookmark loading. + * + * @param observer The observer to add to the static list of observers. + */ + public static void addFaviconUpdateObserver(FaviconUpdateObserver observer) { + sFaviconUpdateObservers.add(observer); + } + + /** + * Removes an observer for favicon updates as a result of fetching favicons from server during + * partner bookmark loading. + * + * @param observer The observer to remove from the static list of observers. + */ + public static void removeFaviconUpdateObserver(FaviconUpdateObserver observer) { + sFaviconUpdateObservers.remove(observer); + } + + /** * Asynchronously read bookmarks from the partner content provider */ public void readBookmarks() { @@ -107,6 +148,14 @@ "PartnerBookmark.FaviconThrottleFetchResult", result, FaviconFetchResult.UMA_BOUNDARY); synchronized (mProgressLock) { + if (result == FaviconFetchResult.SUCCESS_FROM_SERVER) { + // If we've fetched a new favicon from a server, store a flag to indicate + // this so we can refresh bookmarks when all favicons are fetched. + mFaviconsFetchedFromServer = true; + for (FaviconUpdateObserver observer : sFaviconUpdateObservers) { + observer.onUpdateFavicon(nativeGetNativeUrlString(url)); + } + } mFaviconThrottle.onFaviconFetched(url, result); --mNumFaviconsInProgress; if (mNumFaviconsInProgress == 0 && mFinishedReading) { @@ -132,6 +181,7 @@ * down the bookmark reader. */ protected void onBookmarksRead() { + nativePartnerBookmarksCreationComplete(mNativePartnerBookmarksReader); mFinishedReading = true; synchronized (mProgressLock) { if (mNumFaviconsInProgress == 0) { @@ -140,17 +190,26 @@ } } - /** Notifies the reader is complete and partner bookmarks should be submitted to the shim. */ + /** + * Notifies the reader is complete, refreshes the partner bookmarks if necessary, and kills the + * native object + */ protected void shutDown() { synchronized (mProgressLock) { if (mShutDown) return; - nativePartnerBookmarksCreationComplete(mNativePartnerBookmarksReader); - nativeDestroy(mNativePartnerBookmarksReader); - mNativePartnerBookmarksReader = 0; if (mFaviconThrottle != null) { mFaviconThrottle.commit(); } + // Make sure we refresh the bookmarks if we were fetching favicons from server, now that + // we have them all. + if (mFaviconsFetchedFromServer) { + for (FaviconUpdateObserver observer : sFaviconUpdateObservers) { + observer.onCompletedFaviconLoading(); + } + } + nativeDestroy(mNativePartnerBookmarksReader); + mNativePartnerBookmarksReader = 0; mShutDown = true; } } @@ -340,5 +399,6 @@ String title, boolean isFolder, long parentId, byte[] favicon, byte[] touchicon, boolean fetchUncachedFaviconsFromServer, FetchFaviconCallback callback); private native void nativePartnerBookmarksCreationComplete(long nativePartnerBookmarksReader); + private static native String nativeGetNativeUrlString(String url); private static native void nativeDisablePartnerBookmarksEditing(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java index b198cf7..e2e2ecbd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java
@@ -62,6 +62,10 @@ SharedPreferences pref = ContextUtils.getAppSharedPreferences(); long last = pref.getLong(PartnerBookmarksReader.LAST_EMPTY_READ_PREFS_NAME, 0); long elapsed = System.currentTimeMillis() - last; + if (last > 0) { + RecordHistogram.recordCustomTimesHistogram("PartnerBookmark.TimeSinceLastEmptyRead", + elapsed, 1, TimeUnit.DAYS.toMillis(365), TimeUnit.MILLISECONDS, 50); + } // Without checking elapsed >= 0, we might get stuck at an "always skip mode" if // |LAST_EMPTY_READ_PREFS_NAME| is a bogus future time. return 0 <= elapsed && elapsed < BAN_DURATION_MS;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/ChromeHomeAppMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/ChromeHomeAppMenuTest.java index e4d24dd2..6b2e0d7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/ChromeHomeAppMenuTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/ChromeHomeAppMenuTest.java
@@ -8,7 +8,6 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import android.os.Build; import android.support.annotation.Nullable; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; @@ -26,7 +25,6 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; @@ -237,7 +235,6 @@ @Test @SmallTest @CommandLineFlags.Add({"enable-features=" + ChromeFeatureList.CHROME_HOME_PROMO}) - @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.N_MR1, message = "crbug.com/786454") public void testPromoAppMenuHeader() throws InterruptedException, TimeoutException { // Create a callback to be notified when the dialog is shown. final CallbackHelper dialogShownCallback = new CallbackHelper();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottleTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottleTest.java index 5012843..a228a4b 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottleTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottleTest.java
@@ -81,7 +81,7 @@ mFaviconThrottle.init(); Assert.assertFalse(mFaviconThrottle.shouldFetchFromServerIfNecessary("url1")); - mFaviconThrottle.onFaviconFetched("url1", FaviconFetchResult.SUCCESS); + mFaviconThrottle.onFaviconFetched("url1", FaviconFetchResult.SUCCESS_FROM_CACHE); mFaviconThrottle.commit(); mFaviconThrottle.init();
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 6bbd8aa..7ec7d41 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -1638,6 +1638,27 @@ <message name="IDS_SETTINGS_INTERNET_TETHER_PHONE_OUT_OF_RANGE" desc="Text shown when viewing the Tether network detail page when the currently-viewed Tether network has been lost (e.g., has gone out of range). Because Tether networks are provided by Android phones, we use the word 'phone' here instead of 'network'."> Unable to detect your phone </message> + <message name="IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_TITLE" desc="Title of the section which explains how to enable Google Play Services notifications on an Android phone in order to use Instant Tethering."> + Google Play Services notifications are required for Instant Tethering + </message> + <message name="IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_ONE_DEVICE_SUBTITLE" desc="Subtitle of the section which explains how to enable Google Play Services notifications. This subtitle is used when only one phone needs to have its notifications enabled."> + On your '<ph name="PHONE_NAME">$1<ex>Google Pixel</ex></ph>', enable notifications by following these steps: + </message> + <message name="IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_TWO_DEVICES_SUBTITLE" desc="Subtitle of the section which explains how to enable Google Play Services notifications. This subtitle is used when two phones need to have their notifications enabled."> + On your '<ph name="PHONE_NAME_1">$1<ex>Google Pixel</ex></ph>' and '<ph name="PHONE_NAME_2">$2<ex>Google Pixel 2</ex></ph>', enable notifications by following these steps: + </message> + <message name="IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_MANY_DEVICES_SUBTITLE" desc="Subtitle of the section which explains how to enable Google Play Services notifications. This subtitle is used when three or more phones need to have their notifications enabled."> + On your devices, enable notifications by following these steps: + </message> + <message name="IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_FIRST_STEP" desc="First instruction for how to enable Google Play Services notifications on an Android phone. This step teaches the user how to look at Google Play Services settings."> + Go to Settings > Apps & notifications > All apps > Google Play Services. + </message> + <message name="IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_SECOND_STEP" desc="Second instruction for how to enable Google Play Services notifications on an Android phone. This step teaches the user how to look at notification settings when already viewing Google Play Services settings."> + Tap on App notifications. + </message> + <message name="IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_THIRD_STEP" desc="Third instruction for how to enable Google Play Services notifications on an Android phone. This step teaches the user how to enable notifications when already viewing noticiations settings for Google Play Services."> + Check that app notifications are "On". If not, toggle to enable. + </message> <message name="IDS_SETTINGS_INTERNET_NO_NETWORKS_MOBILE_DATA" desc="Text shown when viewing the Mobile data page when there are no cellular or tether networks available."> No mobile connection found. Turn on Instant Tethering on your other devices and try again. <a target="_blank" href="<ph name="URL">$1<ex>https://google.com/</ex></ph>">Learn more</a> </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 7f009d2..5405abb 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -270,9 +270,10 @@ "clipboard/clipboard_write_permission_context.cc", "clipboard/clipboard_write_permission_context.h", "command_observer.h", - "command_updater.cc", "command_updater.h", "command_updater_delegate.h", + "command_updater_impl.cc", + "command_updater_impl.h", "component_updater/chrome_component_updater_configurator.cc", "component_updater/chrome_component_updater_configurator.h", "component_updater/component_updater_prefs.cc", @@ -521,7 +522,6 @@ "gpu/gpu_driver_info_manager_android.h", "gpu/gpu_mode_manager.cc", "gpu/gpu_mode_manager.h", - "gpu/gpu_profile_cache.h", "gpu/three_d_api_observer.cc", "gpu/three_d_api_observer.h", "hang_monitor/hang_crash_dump_win.cc", @@ -2416,8 +2416,6 @@ "first_run/upgrade_util_win.h", "font_family_cache.cc", "font_family_cache.h", - "gpu/gl_string_manager.cc", - "gpu/gl_string_manager.h", "importer/external_process_importer_client.cc", "importer/external_process_importer_client.h", "importer/external_process_importer_host.cc", @@ -3273,6 +3271,7 @@ "printing/pdf_to_emf_converter.cc", "printing/pdf_to_emf_converter.h", ] + deps += [ "//chrome/services/printing/public/interfaces" ] } if (enable_print_preview) { # Full printing on top of the above.
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index b5f300fb..ab9a2e5 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS
@@ -18,6 +18,7 @@ "+chromeos", "+components", "+content/public/browser", + "+content/public/common", "+courgette", "+device/base", "+device/bluetooth", @@ -49,7 +50,7 @@ "+rlz", "+sandbox/win/src", # The path doesn't say it, but this is the Windows sandbox. "+services/data_decoder/public", - "+services/device/public/cpp/device_features.h", + "+services/device/public", "+services/identity/public", "+services/metrics/metrics_mojo_service.h", "+services/metrics/public",
diff --git a/chrome/browser/android/bookmarks/partner_bookmarks_reader.cc b/chrome/browser/android/bookmarks/partner_bookmarks_reader.cc index 9fa0a70..18625ac 100644 --- a/chrome/browser/android/bookmarks/partner_bookmarks_reader.cc +++ b/chrome/browser/android/bookmarks/partner_bookmarks_reader.cc
@@ -28,7 +28,9 @@ using base::android::AttachCurrentThread; using base::android::CheckException; +using base::android::ConvertJavaStringToUTF8; using base::android::ConvertJavaStringToUTF16; +using base::android::ConvertUTF8ToJavaString; using base::android::JavaParamRef; using base::android::JavaRef; using base::android::ScopedJavaGlobalRef; @@ -68,13 +70,11 @@ bookmark_added_event->Signal(); } -void JNI_PartnerBookmarksReader_PrepareAndSetFavicon( - JNIEnv* env, - jbyte* icon_bytes, - int icon_len, - BookmarkNode* node, - Profile* profile, - favicon_base::IconType icon_type) { +void PrepareAndSetFavicon(jbyte* icon_bytes, + int icon_len, + BookmarkNode* node, + Profile* profile, + favicon_base::IconType icon_type) { SkBitmap icon_bitmap; if (!gfx::PNGCodec::Decode( reinterpret_cast<const unsigned char*>(icon_bytes), @@ -177,8 +177,8 @@ const int icon_len = env->GetArrayLength(icon); jbyte* icon_bytes = env->GetByteArrayElements(icon, nullptr); if (icon_bytes) - JNI_PartnerBookmarksReader_PrepareAndSetFavicon( - env, icon_bytes, icon_len, node.get(), profile_, icon_type); + PrepareAndSetFavicon(icon_bytes, icon_len, node.get(), profile_, + icon_type); env->ReleaseByteArrayElements(icon, icon_bytes, JNI_ABORT); } else { // We should attempt to read the favicon from cache or retrieve it from @@ -234,7 +234,7 @@ } GetFaviconFromCacheOrServer(page_url, fallback_to_server, - std::move(callback)); + false /* from_server */, std::move(callback)); } favicon::LargeIconService* PartnerBookmarksReader::GetLargeIconService() { @@ -248,12 +248,14 @@ void PartnerBookmarksReader::GetFaviconFromCacheOrServer( const GURL& page_url, bool fallback_to_server, + bool from_server, FaviconFetchedCallback callback) { GetLargeIconService()->GetLargeIconOrFallbackStyle( page_url, kPartnerBookmarksMinimumFaviconSizePx, 0, base::Bind(&PartnerBookmarksReader::OnGetFaviconFromCacheFinished, base::Unretained(this), page_url, - base::Passed(std::move(callback)), fallback_to_server), + base::Passed(std::move(callback)), fallback_to_server, + from_server), &favicon_task_tracker_); } @@ -261,10 +263,17 @@ const GURL& page_url, FaviconFetchedCallback callback, bool fallback_to_server, + bool from_server, const favicon_base::LargeIconResult& result) { - // We got an image from the cache. + // |from_server| tells us if we fetched the image from the cache after we went + // to server for it, so this successful cache retrieval should actually return + // SUCCESS_FROM_SERVER. if (result.bitmap.is_valid()) { - std::move(callback).Run(FaviconFetchResult::SUCCESS); + if (from_server) { + std::move(callback).Run(FaviconFetchResult::SUCCESS_FROM_SERVER); + } else { + std::move(callback).Run(FaviconFetchResult::SUCCESS_FROM_CACHE); + } return; } @@ -309,18 +318,24 @@ FaviconFetchedCallback callback, favicon_base::GoogleFaviconServerRequestStatus status) { if (status != favicon_base::GoogleFaviconServerRequestStatus::SUCCESS) { - std::move(callback).Run( - status == favicon_base::GoogleFaviconServerRequestStatus:: - FAILURE_CONNECTION_ERROR - ? FaviconFetchResult::FAILURE_CONNECTION_ERROR - : FaviconFetchResult::FAILURE_SERVER_ERROR); + FaviconFetchResult result; + if (status == favicon_base::GoogleFaviconServerRequestStatus:: + FAILURE_CONNECTION_ERROR) { + result = FaviconFetchResult::FAILURE_CONNECTION_ERROR; + } else if (status == favicon_base::GoogleFaviconServerRequestStatus:: + FAILURE_ON_WRITE) { + result = FaviconFetchResult::FAILURE_WRITING_FAVICON_CACHE; + } else { + result = FaviconFetchResult::FAILURE_SERVER_ERROR; + } + std::move(callback).Run(result); return; } // The icon was successfully retrieved from the server, now we just have to // retrieve it from the cache where it was stored. GetFaviconFromCacheOrServer(page_url, false /* fallback_to_server */, - std::move(callback)); + true /* from_server */, std::move(callback)); } void PartnerBookmarksReader::OnFaviconFetched( @@ -331,15 +346,14 @@ static_cast<int>(result)); } -// static +// ---------------------------------------------------------------- + static void JNI_PartnerBookmarksReader_DisablePartnerBookmarksEditing( JNIEnv* env, const JavaParamRef<jclass>& clazz) { PartnerBookmarksShim::DisablePartnerBookmarksEditing(); } -// ---------------------------------------------------------------- - static jlong JNI_PartnerBookmarksReader_Init(JNIEnv* env, const JavaParamRef<jobject>& obj) { Profile* profile = ProfileManager::GetActiveUserProfile(); @@ -349,3 +363,12 @@ partner_bookmarks_shim, profile); return reinterpret_cast<intptr_t>(reader); } + +static base::android::ScopedJavaLocalRef<jstring> +JNI_PartnerBookmarksReader_GetNativeUrlString( + JNIEnv* env, + const JavaParamRef<jclass>& clazz, + const JavaParamRef<jstring>& j_url) { + GURL url(ConvertJavaStringToUTF8(j_url)); + return ConvertUTF8ToJavaString(env, url.spec()); +}
diff --git a/chrome/browser/android/bookmarks/partner_bookmarks_reader.h b/chrome/browser/android/bookmarks/partner_bookmarks_reader.h index 3f940dfa1..728c702 100644 --- a/chrome/browser/android/bookmarks/partner_bookmarks_reader.h +++ b/chrome/browser/android/bookmarks/partner_bookmarks_reader.h
@@ -53,17 +53,26 @@ // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.partnerbookmarks enum class FaviconFetchResult { // Successfully fetched a favicon from cache or server. - SUCCESS = 0, + // Deprecated, SUCCESS_FROM_CACHE and SUCCESS_FROM_SERVER should be used. + DEPRECATED_SUCCESS = 0, // Received a server error fetching the favicon. - FAILURE_SERVER_ERROR = 1, + FAILURE_SERVER_ERROR, // The icon service was unavailable. - FAILURE_ICON_SERVICE_UNAVAILABLE = 2, + FAILURE_ICON_SERVICE_UNAVAILABLE, // There was nothing in the cache, but we opted out of retrieving from // server. - FAILURE_NOT_IN_CACHE = 3, + FAILURE_NOT_IN_CACHE, // Request sent out and a connection error occurred (no valid HTTP response // received). - FAILURE_CONNECTION_ERROR = 4, + FAILURE_CONNECTION_ERROR, + // Success fetching the favicon from the cache without reaching out to the + // server. + SUCCESS_FROM_CACHE, + // Success fetching the favicon from server. + SUCCESS_FROM_SERVER, + // Failed to write the favicon to cache, likely from attempting to add a + // duplicate. + FAILURE_WRITING_FAVICON_CACHE, // Boundary value for UMA. UMA_BOUNDARY, }; @@ -81,11 +90,13 @@ FaviconFetchedCallback callback); void GetFaviconFromCacheOrServer(const GURL& page_url, bool fallback_to_server, + bool from_server, FaviconFetchedCallback callback); void OnGetFaviconFromCacheFinished( const GURL& page_url, FaviconFetchedCallback callback, bool fallback_to_server, + bool from_server, const favicon_base::LargeIconResult& result); void OnGetFaviconFromServerFinished( const GURL& page_url,
diff --git a/chrome/browser/android/vr_shell/autocomplete_controller.cc b/chrome/browser/android/vr_shell/autocomplete_controller.cc index e22426f..070dd01 100644 --- a/chrome/browser/android/vr_shell/autocomplete_controller.cc +++ b/chrome/browser/android/vr_shell/autocomplete_controller.cc
@@ -19,7 +19,7 @@ namespace { constexpr size_t kMaxNumberOfSuggestions = 4; -constexpr int kSuggestionThrottlingDelayMs = 300; +constexpr int kSuggestionThrottlingDelayMs = 150; } // namespace AutocompleteController::AutocompleteController(vr::BrowserUiInterface* ui)
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm index 385cf9e..398ec6e 100644 --- a/chrome/browser/app_controller_mac.mm +++ b/chrome/browser/app_controller_mac.mm
@@ -6,6 +6,8 @@ #include <stddef.h> +#include <memory> + #include "base/allocator/allocator_shim.h" #include "base/allocator/features.h" #include "base/auto_reset.h" @@ -34,7 +36,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_shutdown.h" #include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/command_updater.h" +#include "chrome/browser/command_updater_impl.h" #include "chrome/browser/download/download_core_service.h" #include "chrome/browser/download/download_core_service_factory.h" #include "chrome/browser/extensions/extension_service.h" @@ -1249,7 +1251,7 @@ } - (void)initMenuState { - menuState_.reset(new CommandUpdater(NULL)); + menuState_ = std::make_unique<CommandUpdaterImpl>(nullptr); menuState_->UpdateCommandEnabled(IDC_NEW_TAB, true); menuState_->UpdateCommandEnabled(IDC_NEW_WINDOW, true); menuState_->UpdateCommandEnabled(IDC_NEW_INCOGNITO_WINDOW, true);
diff --git a/chrome/browser/apps/guest_view/app_view_browsertest.cc b/chrome/browser/apps/guest_view/app_view_browsertest.cc index dc4ac3f..9ef97e3 100644 --- a/chrome/browser/apps/guest_view/app_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/app_view_browsertest.cc
@@ -196,8 +196,13 @@ } // Tests that <appview> correctly handles multiple successive connects. -// TODO(crbug.com/794490) Reenable after fixing timeout issues. -IN_PROC_BROWSER_TEST_P(AppViewTest, DISABLED_TestAppViewMultipleConnects) { +IN_PROC_BROWSER_TEST_P(AppViewTest, TestAppViewMultipleConnects) { + // TODO(crbug.com/794490) Skip this test for the BrowserPlugin ("/0") + // case until we either (i) find the cause of the TIMEOUT or (ii) + // remove BrowserPlugin. + if (!GetParam()) + return; + const extensions::Extension* skeleton_app = InstallPlatformApp("app_view/shim/skeleton"); TestHelper("testAppViewMultipleConnects",
diff --git a/chrome/browser/browser_commands_unittest.cc b/chrome/browser/browser_commands_unittest.cc index bb619997..22d9a229 100644 --- a/chrome/browser/browser_commands_unittest.cc +++ b/chrome/browser/browser_commands_unittest.cc
@@ -46,7 +46,7 @@ // Select the second tab. browser()->tab_strip_model()->ActivateTabAt(1, false); - CommandUpdater* updater = browser()->command_controller()->command_updater(); + CommandUpdater* updater = browser()->command_controller(); // Navigate to the first tab using an accelerator. updater->ExecuteCommand(IDC_SELECT_TAB_0);
diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h index 4f2db4b..deff1e0 100644 --- a/chrome/browser/browser_process.h +++ b/chrome/browser/browser_process.h
@@ -25,8 +25,10 @@ class BackgroundModeManager; class DownloadRequestLimiter; class DownloadStatusUpdater; +#if defined(OS_ANDROID) +class GpuDriverInfoManager; +#endif class GpuModeManager; -class GpuProfileCache; class IconManager; class IntranetRedirectDetector; class IOThread; @@ -211,7 +213,9 @@ virtual GpuModeManager* gpu_mode_manager() = 0; - virtual GpuProfileCache* gpu_profile_cache() = 0; +#if defined(OS_ANDROID) + virtual GpuDriverInfoManager* gpu_driver_info_manager() = 0; +#endif // Create and bind remote debugging server to a given |ip| and |port|. // Passing empty |ip| results in binding to localhost:
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index 575f8d0..8002e031 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc
@@ -49,7 +49,6 @@ #include "chrome/browser/download/download_request_limiter.h" #include "chrome/browser/download/download_status_updater.h" #include "chrome/browser/gpu/gpu_mode_manager.h" -#include "chrome/browser/gpu/gpu_profile_cache.h" #include "chrome/browser/icon_manager.h" #include "chrome/browser/intranet_redirect_detector.h" #include "chrome/browser/io_thread.h" @@ -183,6 +182,7 @@ #if defined(OS_ANDROID) #include "chrome/browser/android/physical_web/physical_web_data_source_android.h" +#include "chrome/browser/gpu/gpu_driver_info_manager_android.h" #endif #if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS) @@ -678,12 +678,14 @@ return icon_manager_.get(); } -GpuProfileCache* BrowserProcessImpl::gpu_profile_cache() { +#if defined(OS_ANDROID) +GpuDriverInfoManager* BrowserProcessImpl::gpu_driver_info_manager() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!gpu_profile_cache_) - gpu_profile_cache_ = GpuProfileCache::Create(); - return gpu_profile_cache_.get(); + if (!gpu_driver_info_manager_) + gpu_driver_info_manager_ = GpuDriverInfoManager::Create(); + return gpu_driver_info_manager_.get(); } +#endif GpuModeManager* BrowserProcessImpl::gpu_mode_manager() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h index 1af54260..1d2cedd 100644 --- a/chrome/browser/browser_process_impl.h +++ b/chrome/browser/browser_process_impl.h
@@ -116,7 +116,9 @@ policy::PolicyService* policy_service() override; IconManager* icon_manager() override; GpuModeManager* gpu_mode_manager() override; - GpuProfileCache* gpu_profile_cache() override; +#if defined(OS_ANDROID) + GpuDriverInfoManager* gpu_driver_info_manager() override; +#endif void CreateDevToolsHttpProtocolHandler(const std::string& ip, uint16_t port) override; void CreateDevToolsAutoOpener() override; @@ -227,7 +229,9 @@ bool created_icon_manager_; std::unique_ptr<IconManager> icon_manager_; - std::unique_ptr<GpuProfileCache> gpu_profile_cache_; +#if defined(OS_ANDROID) + std::unique_ptr<GpuDriverInfoManager> gpu_driver_info_manager_; +#endif std::unique_ptr<GpuModeManager> gpu_mode_manager_;
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 8d5642b..2016723 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc
@@ -70,7 +70,6 @@ #include "chrome/browser/defaults.h" #include "chrome/browser/experiments/memory_ablation_experiment.h" #include "chrome/browser/first_run/first_run.h" -#include "chrome/browser/gpu/gpu_profile_cache.h" #include "chrome/browser/gpu/three_d_api_observer.h" #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h" #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" @@ -185,6 +184,7 @@ #include "ui/base/resource/resource_bundle.h" #if defined(OS_ANDROID) +#include "chrome/browser/gpu/gpu_driver_info_manager_android.h" #include "chrome/browser/metrics/thread_watcher_android.h" #include "ui/base/resource/resource_bundle_android.h" #else @@ -901,15 +901,17 @@ chrome_extra_parts_[i]->PreCreateThreads(); } +#if defined(OS_ANDROID) // It is important to call gpu_profile_cache()->Initialize() before // starting the gpu process. Internally it properly setup the black listed // features. Which it is used to decide whether to start or not the gpu // process from BrowserMainLoop::BrowserThreadsStarted. // Retrieve cached GL strings from local state and use them for GPU - // blacklist decisions. - if (g_browser_process->gpu_profile_cache()) - g_browser_process->gpu_profile_cache()->Initialize(); + // blacklist decisions. Currently this is only done on Android. + if (g_browser_process->gpu_driver_info_manager()) + g_browser_process->gpu_driver_info_manager()->Initialize(); +#endif // OS_ANDROID // Create an instance of GpuModeManager to watch gpu mode pref change. g_browser_process->gpu_mode_manager();
diff --git a/chrome/browser/chrome_content_browser_manifest_overlay.json b/chrome/browser/chrome_content_browser_manifest_overlay.json index df5e1c1..7d018655 100644 --- a/chrome/browser/chrome_content_browser_manifest_overlay.json +++ b/chrome/browser/chrome_content_browser_manifest_overlay.json
@@ -33,7 +33,10 @@ "chrome": [ "input_device_controller" ], "chrome_printing": [ "converter" ], "content_browser": [ "profiling_client" ], - "device": [ "device:fingerprint" ], + "device": [ + "device:fingerprint", + "device:geolocation_control" + ], "file_util": [ "analyze_archive", "zip_file" ], "identity": [ "identity_manager" ], // Only used in classic ash case.
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index b98f315..93a32aa 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -1744,6 +1744,8 @@ "arc/process/arc_process_unittest.cc", "arc/tts/arc_tts_service_unittest.cc", "arc/voice_interaction/arc_voice_interaction_framework_service_unittest.cc", + "arc/voice_interaction/fake_voice_interaction_controller.cc", + "arc/voice_interaction/voice_interaction_controller_client_unittest.cc", "arc/wallpaper/arc_wallpaper_service_unittest.cc", "attestation/attestation_ca_client_unittest.cc", "attestation/attestation_policy_observer_unittest.cc",
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc index d79e2451..2f7c636 100644 --- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc +++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -149,6 +149,23 @@ DISALLOW_COPY_AND_ASSIGN(ChromeVoxPanelWidgetObserver); }; +class ScopedKeyboardStateSetter { + public: + ScopedKeyboardStateSetter() : is_enabled_(keyboard::IsKeyboardEnabled()) { + keyboard::SetRequestedKeyboardState(keyboard::KEYBOARD_STATE_ENABLED); + } + + ~ScopedKeyboardStateSetter() { + if (!is_enabled_) + keyboard::SetRequestedKeyboardState(keyboard::KEYBOARD_STATE_DISABLED); + } + + private: + bool is_enabled_; + + DISALLOW_COPY_AND_ASSIGN(ScopedKeyboardStateSetter); +}; + /////////////////////////////////////////////////////////////////////////////// // AccessibilityStatusEventDetails @@ -1459,6 +1476,8 @@ base::CommandLine::ForCurrentProcess()->AppendSwitch( ::switches::kEnableAudioFocus); } + + keyboard_state_setter_.reset(new ScopedKeyboardStateSetter()); } void AccessibilityManager::PostUnloadChromeVox() { @@ -1477,6 +1496,8 @@ // In case the user darkened the screen, undarken it now. scoped_backlights_forced_off_.reset(); + + keyboard_state_setter_.reset(); } void AccessibilityManager::PostSwitchChromeVoxProfile() {
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.h b/chrome/browser/chromeos/accessibility/accessibility_manager.h index 3e86f1f..f1d2e54 100644 --- a/chrome/browser/chromeos/accessibility/accessibility_manager.h +++ b/chrome/browser/chromeos/accessibility/accessibility_manager.h
@@ -41,6 +41,7 @@ class AccessibilityExtensionLoader; class AccessibilityHighlightManager; +class ScopedKeyboardStateSetter; class SelectToSpeakEventHandler; class SwitchAccessEventHandler; @@ -449,6 +450,8 @@ // Used to force the backlights off to darken the screen. std::unique_ptr<ash::ScopedBacklightsForcedOff> scoped_backlights_forced_off_; + std::unique_ptr<ScopedKeyboardStateSetter> keyboard_state_setter_; + base::WeakPtrFactory<AccessibilityManager> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(AccessibilityManager);
diff --git a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc index 24e9162..c5af839 100644 --- a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc +++ b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
@@ -526,8 +526,6 @@ if (utterance == "Click me") break; } - speech_monitor_.GetNextUtterance(); - EXPECT_EQ("Button", speech_monitor_.GetNextUtterance()); // Press Search+/ to enter ChromeVox's "find in page". SendKeyPressWithSearch(ui::VKEY_OEM_2);
diff --git a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.cc b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.cc index 9db526b..07bdf5d9 100644 --- a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.cc +++ b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.cc
@@ -232,19 +232,15 @@ : context_(context), arc_bridge_service_(bridge_service), highlighter_client_(std::make_unique<HighlighterControllerClient>(this)), - voice_interaction_controller_client_( - std::make_unique<VoiceInteractionControllerClient>()), weak_ptr_factory_(this) { arc_bridge_service_->voice_interaction_framework()->SetHost(this); arc_bridge_service_->voice_interaction_framework()->AddObserver(this); ArcSessionManager::Get()->AddObserver(this); - session_manager::SessionManager::Get()->AddObserver(this); chromeos::CrasAudioHandler::Get()->AddAudioObserver(this); } ArcVoiceInteractionFrameworkService::~ArcVoiceInteractionFrameworkService() { chromeos::CrasAudioHandler::Get()->RemoveAudioObserver(this); - session_manager::SessionManager::Get()->RemoveObserver(this); ArcSessionManager::Get()->RemoveObserver(this); arc_bridge_service_->voice_interaction_framework()->RemoveObserver(this); arc_bridge_service_->voice_interaction_framework()->SetHost(nullptr); @@ -337,7 +333,7 @@ highlighter_client_->Exit(); state_ = state; - voice_interaction_controller_client_->NotifyStatusChanged(state); + arc::VoiceInteractionControllerClient::Get()->NotifyStatusChanged(state); } void ArcVoiceInteractionFrameworkService::ShowMetalayer() { @@ -353,9 +349,6 @@ void ArcVoiceInteractionFrameworkService::OnArcPlayStoreEnabledChanged( bool enabled) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - voice_interaction_controller_client_->NotifyFeatureAllowed( - IsAssistantAllowedForProfile(Profile::FromBrowserContext(context_))); - if (enabled) return; @@ -364,33 +357,6 @@ SetVoiceInteractionContextEnabled(false); } -void ArcVoiceInteractionFrameworkService::OnSessionStateChanged() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - session_manager::SessionState session_state = - session_manager::SessionManager::Get()->session_state(); - if (session_state != session_manager::SessionState::ACTIVE) - return; - - Profile* profile = Profile::FromBrowserContext(context_); - PrefService* prefs = profile->GetPrefs(); - bool enabled = prefs->GetBoolean(prefs::kVoiceInteractionEnabled); - voice_interaction_controller_client_->NotifySettingsEnabled(enabled); - - bool context = prefs->GetBoolean(prefs::kVoiceInteractionContextEnabled); - voice_interaction_controller_client_->NotifyContextEnabled(context); - - bool setup_completed = - prefs->GetBoolean(prefs::kArcVoiceInteractionValuePropAccepted); - voice_interaction_controller_client_->NotifySetupCompleted(setup_completed); - - voice_interaction_controller_client_->NotifyFeatureAllowed( - IsAssistantAllowedForProfile(profile)); - - // We only want notify the status change on first user signed in. - session_manager::SessionManager::Get()->RemoveObserver(this); -} - void ArcVoiceInteractionFrameworkService::OnHotwordTriggered(uint64_t tv_sec, uint64_t tv_nsec) { InitiateUserInteraction(false /* is_toggle */); @@ -450,8 +416,6 @@ VoiceInteractionSettingCompleteCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - voice_interaction_controller_client_->NotifySettingsEnabled(enable); - PrefService* prefs = Profile::FromBrowserContext(context_)->GetPrefs(); prefs->SetBoolean(prefs::kVoiceInteractionEnabled, enable); @@ -474,8 +438,6 @@ bool enable) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - voice_interaction_controller_client_->NotifyContextEnabled(enable); - PrefService* prefs = Profile::FromBrowserContext(context_)->GetPrefs(); prefs->SetBoolean(prefs::kVoiceInteractionContextEnabled, enable); @@ -593,7 +555,7 @@ if (state_ == ash::mojom::VoiceInteractionState::NOT_READY) { // If the container side is not ready, we will be waiting for a while. - voice_interaction_controller_client_->NotifyStatusChanged( + arc::VoiceInteractionControllerClient::Get()->NotifyStatusChanged( ash::mojom::VoiceInteractionState::NOT_READY); } @@ -615,8 +577,6 @@ SetVoiceInteractionSetupCompletedInternal(bool completed) { PrefService* prefs = Profile::FromBrowserContext(context_)->GetPrefs(); prefs->SetBoolean(prefs::kArcVoiceInteractionValuePropAccepted, completed); - - voice_interaction_controller_client_->NotifySetupCompleted(completed); } bool ArcVoiceInteractionFrameworkService::IsHomescreenActive() {
diff --git a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.h b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.h index f0bbf0d2..ba27f59 100644 --- a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.h +++ b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.h
@@ -17,7 +17,6 @@ #include "components/arc/common/voice_interaction_framework.mojom.h" #include "components/arc/connection_observer.h" #include "components/keyed_service/core/keyed_service.h" -#include "components/session_manager/core/session_manager_observer.h" class KeyedServiceBaseFactory; @@ -33,7 +32,6 @@ class ArcBridgeService; class HighlighterControllerClient; -class VoiceInteractionControllerClient; // This provides voice interaction context (currently screenshots) // to ARC to be used by VoiceInteractionSession. This class lives on the UI @@ -43,8 +41,7 @@ public KeyedService, public mojom::VoiceInteractionFrameworkHost, public ConnectionObserver<mojom::VoiceInteractionFrameworkInstance>, - public ArcSessionManager::Observer, - public session_manager::SessionManagerObserver { + public ArcSessionManager::Observer { public: // Returns singleton instance for the given BrowserContext, // or nullptr if the browser |context| is not allowed to use ARC. @@ -73,9 +70,6 @@ // ArcSessionManager::Observer overrides. void OnArcPlayStoreEnabledChanged(bool enabled) override; - // session_manager::SessionManagerObserver overrides. - void OnSessionStateChanged() override; - // CrasAudioHandler::AudioObserver overrides. void OnHotwordTriggered(uint64_t tv_sec, uint64_t tv_nsec) override; @@ -129,11 +123,6 @@ return state_; } - VoiceInteractionControllerClient* - GetVoiceInteractionControllerClientForTesting() const { - return voice_interaction_controller_client_.get(); - } - // For supporting ArcServiceManager::GetService<T>(). static const char kArcServiceName[]; @@ -179,9 +168,6 @@ std::unique_ptr<HighlighterControllerClient> highlighter_client_; - std::unique_ptr<VoiceInteractionControllerClient> - voice_interaction_controller_client_; - base::WeakPtrFactory<ArcVoiceInteractionFrameworkService> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(ArcVoiceInteractionFrameworkService);
diff --git a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service_unittest.cc b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service_unittest.cc index b03bd3b..d897c35 100644 --- a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service_unittest.cc +++ b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service_unittest.cc
@@ -13,6 +13,7 @@ #include "base/bind.h" #include "base/files/scoped_temp_dir.h" #include "chrome/browser/chromeos/arc/arc_session_manager.h" +#include "chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.h" #include "chrome/browser/chromeos/arc/voice_interaction/highlighter_controller_client.h" #include "chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.h" #include "chrome/test/base/testing_profile.h" @@ -92,65 +93,6 @@ DISALLOW_COPY_AND_ASSIGN(TestHighlighterController); }; -class TestVoiceInteractionController - : public ash::mojom::VoiceInteractionController { - public: - TestVoiceInteractionController() : binding_(this) {} - ~TestVoiceInteractionController() override = default; - - ash::mojom::VoiceInteractionControllerPtr CreateInterfacePtrAndBind() { - ash::mojom::VoiceInteractionControllerPtr ptr; - binding_.Bind(mojo::MakeRequest(&ptr)); - return ptr; - } - - // ash::mojom::VoiceInteractionController: - void NotifyStatusChanged(ash::mojom::VoiceInteractionState state) override { - voice_interaction_state_ = state; - } - void NotifySettingsEnabled(bool enabled) override { - voice_interaction_settings_enabled_ = enabled; - } - void NotifyContextEnabled(bool enabled) override { - voice_interaction_context_enabled_ = enabled; - } - void NotifySetupCompleted(bool completed) override { - voice_interaction_setup_completed_ = completed; - } - void NotifyFeatureAllowed(ash::mojom::AssistantAllowedState state) override { - assistant_allowed_state_ = state; - } - - ash::mojom::VoiceInteractionState voice_interaction_state() const { - return voice_interaction_state_; - } - bool voice_interaction_settings_enabled() const { - return voice_interaction_settings_enabled_; - } - bool voice_interaction_context_enabled() const { - return voice_interaction_context_enabled_; - } - bool voice_interaction_setup_completed() const { - return voice_interaction_setup_completed_; - } - ash::mojom::AssistantAllowedState assistant_allowed_state() const { - return assistant_allowed_state_; - } - - private: - ash::mojom::VoiceInteractionState voice_interaction_state_ = - ash::mojom::VoiceInteractionState::STOPPED; - bool voice_interaction_settings_enabled_ = false; - bool voice_interaction_context_enabled_ = false; - bool voice_interaction_setup_completed_ = false; - ash::mojom::AssistantAllowedState assistant_allowed_state_ = - ash::mojom::AssistantAllowedState::ALLOWED; - - mojo::Binding<ash::mojom::VoiceInteractionController> binding_; - - DISALLOW_COPY_AND_ASSIGN(TestVoiceInteractionController); -}; - } // namespace class ArcVoiceInteractionFrameworkServiceTest : public ash::AshTestBase { @@ -177,7 +119,9 @@ std::make_unique<TestHighlighterController>(); highlighter_controller_ = highlighter_controller_ptr.get(); voice_interaction_controller_ = - std::make_unique<TestVoiceInteractionController>(); + std::make_unique<FakeVoiceInteractionController>(); + voice_interaction_controller_client_ = + std::make_unique<VoiceInteractionControllerClient>(); connector_factory_ = std::make_unique<service_manager::TestConnectorFactory>( std::move(highlighter_controller_ptr)); @@ -206,6 +150,8 @@ void TearDown() override { arc_bridge_service_->voice_interaction_framework()->CloseInstance( framework_instance_.get()); + voice_interaction_controller_.reset(); + voice_interaction_controller_client_.reset(); framework_instance_.reset(); framework_service_.reset(); arc_bridge_service_.reset(); @@ -232,12 +178,12 @@ return highlighter_controller_; } - TestVoiceInteractionController* voice_interaction_controller() { + FakeVoiceInteractionController* voice_interaction_controller() { return voice_interaction_controller_.get(); } VoiceInteractionControllerClient* voice_interaction_controller_client() { - return framework_service_->GetVoiceInteractionControllerClientForTesting(); + return voice_interaction_controller_client_.get(); } void FlushHighlighterControllerMojo() { @@ -258,9 +204,11 @@ std::unique_ptr<service_manager::Connector> connector_; // |highlighter_controller_| is valid until |connector_factory_| is deleted. TestHighlighterController* highlighter_controller_; - std::unique_ptr<TestVoiceInteractionController> voice_interaction_controller_; + std::unique_ptr<FakeVoiceInteractionController> voice_interaction_controller_; std::unique_ptr<ArcVoiceInteractionFrameworkService> framework_service_; std::unique_ptr<FakeVoiceInteractionFrameworkInstance> framework_instance_; + std::unique_ptr<VoiceInteractionControllerClient> + voice_interaction_controller_client_; DISALLOW_COPY_AND_ASSIGN(ArcVoiceInteractionFrameworkServiceTest); }; @@ -417,44 +365,19 @@ TEST_F(ArcVoiceInteractionFrameworkServiceTest, VoiceInteractionControllerClient) { - TestVoiceInteractionController* controller = voice_interaction_controller(); + FakeVoiceInteractionController* controller = voice_interaction_controller(); VoiceInteractionControllerClient* controller_client = voice_interaction_controller_client(); // The voice interaction flags should be set after the initial setup. - EXPECT_TRUE(controller->voice_interaction_settings_enabled()); - EXPECT_TRUE(controller->voice_interaction_context_enabled()); - EXPECT_TRUE(controller->voice_interaction_setup_completed()); EXPECT_EQ(controller->voice_interaction_state(), ash::mojom::VoiceInteractionState::STOPPED); - // Send the signal to disable voice interaction settings. - controller_client->NotifySettingsEnabled(false); - FlushVoiceInteractionControllerMojo(); - EXPECT_FALSE(controller->voice_interaction_settings_enabled()); - - // Send the signal to disable voice interaction context. - controller_client->NotifyContextEnabled(false); - FlushVoiceInteractionControllerMojo(); - EXPECT_FALSE(controller->voice_interaction_context_enabled()); - - // Send the signal to disable the voice interaction setup completed flag. - controller_client->NotifySetupCompleted(false); - FlushVoiceInteractionControllerMojo(); - EXPECT_FALSE(controller->voice_interaction_setup_completed()); - // Send the signal to set the voice interaction state. controller_client->NotifyStatusChanged( ash::mojom::VoiceInteractionState::RUNNING); FlushVoiceInteractionControllerMojo(); EXPECT_EQ(controller->voice_interaction_state(), ash::mojom::VoiceInteractionState::RUNNING); - - // Send the signal to set the assistant allowed state. - controller_client->NotifyFeatureAllowed( - ash::mojom::AssistantAllowedState::DISALLOWED_BY_ARC_POLICY); - FlushVoiceInteractionControllerMojo(); - EXPECT_EQ(controller->assistant_allowed_state(), - ash::mojom::AssistantAllowedState::DISALLOWED_BY_ARC_POLICY); } } // namespace arc
diff --git a/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.cc b/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.cc new file mode 100644 index 0000000..f1048b4 --- /dev/null +++ b/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.cc
@@ -0,0 +1,43 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.h" + +namespace arc { + +FakeVoiceInteractionController::FakeVoiceInteractionController() + : binding_(this) {} + +FakeVoiceInteractionController::~FakeVoiceInteractionController() = default; + +ash::mojom::VoiceInteractionControllerPtr +FakeVoiceInteractionController::CreateInterfacePtrAndBind() { + ash::mojom::VoiceInteractionControllerPtr ptr; + binding_.Bind(mojo::MakeRequest(&ptr)); + return ptr; +} + +void FakeVoiceInteractionController::NotifyStatusChanged( + ash::mojom::VoiceInteractionState state) { + voice_interaction_state_ = state; +} + +void FakeVoiceInteractionController::NotifySettingsEnabled(bool enabled) { + voice_interaction_settings_enabled_ = enabled; +} + +void FakeVoiceInteractionController::NotifyContextEnabled(bool enabled) { + voice_interaction_context_enabled_ = enabled; +} + +void FakeVoiceInteractionController::NotifySetupCompleted(bool completed) { + voice_interaction_setup_completed_ = completed; +} + +void FakeVoiceInteractionController::NotifyFeatureAllowed( + ash::mojom::AssistantAllowedState state) { + assistant_allowed_state_ = state; +} + +} // namespace arc
diff --git a/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.h b/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.h new file mode 100644 index 0000000..a84c36b --- /dev/null +++ b/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.h
@@ -0,0 +1,60 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_ARC_VOICE_INTERACTION_TEST_VOICE_INTERACTION_CONTROLLER_H_ +#define CHROME_BROWSER_CHROMEOS_ARC_VOICE_INTERACTION_TEST_VOICE_INTERACTION_CONTROLLER_H_ + +#include "ash/public/interfaces/voice_interaction_controller.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" + +namespace arc { + +class FakeVoiceInteractionController + : public ash::mojom::VoiceInteractionController { + public: + FakeVoiceInteractionController(); + ~FakeVoiceInteractionController() override; + + ash::mojom::VoiceInteractionControllerPtr CreateInterfacePtrAndBind(); + + // ash::mojom::VoiceInteractionController: + void NotifyStatusChanged(ash::mojom::VoiceInteractionState state) override; + void NotifySettingsEnabled(bool enabled) override; + void NotifyContextEnabled(bool enabled) override; + void NotifySetupCompleted(bool completed) override; + void NotifyFeatureAllowed(ash::mojom::AssistantAllowedState state) override; + + ash::mojom::VoiceInteractionState voice_interaction_state() const { + return voice_interaction_state_; + } + bool voice_interaction_settings_enabled() const { + return voice_interaction_settings_enabled_; + } + bool voice_interaction_context_enabled() const { + return voice_interaction_context_enabled_; + } + bool voice_interaction_setup_completed() const { + return voice_interaction_setup_completed_; + } + ash::mojom::AssistantAllowedState assistant_allowed_state() const { + return assistant_allowed_state_; + } + + private: + ash::mojom::VoiceInteractionState voice_interaction_state_ = + ash::mojom::VoiceInteractionState::STOPPED; + bool voice_interaction_settings_enabled_ = false; + bool voice_interaction_context_enabled_ = false; + bool voice_interaction_setup_completed_ = false; + ash::mojom::AssistantAllowedState assistant_allowed_state_ = + ash::mojom::AssistantAllowedState::DISALLOWED_BY_INCOGNITO; + + mojo::Binding<ash::mojom::VoiceInteractionController> binding_; + + DISALLOW_COPY_AND_ASSIGN(FakeVoiceInteractionController); +}; + +} // namespace arc + +#endif // CHROME_BROWSER_CHROMEOS_ARC_VOICE_INTERACTION_TEST_VOICE_INTERACTION_CONTROLLER_H_
diff --git a/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.cc b/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.cc index 6e95cbd..8102964 100644 --- a/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.cc +++ b/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.cc
@@ -6,45 +6,60 @@ #include <utility> +#include "ash/public/cpp/ash_pref_names.h" #include "ash/public/interfaces/constants.mojom.h" +#include "base/bind.h" +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/chromeos/arc/arc_util.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "components/arc/arc_prefs.h" +#include "components/arc/arc_util.h" +#include "components/prefs/pref_service.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/notification_source.h" #include "content/public/common/service_manager_connection.h" #include "services/service_manager/public/cpp/connector.h" namespace arc { +namespace { + +// Weak pointer. This class is owned by ChromeBrowserMainPartsChromeos. +VoiceInteractionControllerClient* g_instance = nullptr; + +} // namespace + VoiceInteractionControllerClient::VoiceInteractionControllerClient() { + DCHECK(!g_instance); ConnectToVoiceInteractionController(); + + notification_registrar_.Add(this, + chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED, + content::NotificationService::AllSources()); + notification_registrar_.Add(this, chrome::NOTIFICATION_SESSION_STARTED, + content::NotificationService::AllSources()); + notification_registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, + content::NotificationService::AllSources()); + + g_instance = this; } -VoiceInteractionControllerClient::~VoiceInteractionControllerClient() = default; +VoiceInteractionControllerClient::~VoiceInteractionControllerClient() { + DCHECK_EQ(g_instance, this); + g_instance = nullptr; +} + +// static +VoiceInteractionControllerClient* VoiceInteractionControllerClient::Get() { + return g_instance; +} void VoiceInteractionControllerClient::NotifyStatusChanged( ash::mojom::VoiceInteractionState state) { - DCHECK(voice_interaction_controller_); voice_interaction_controller_->NotifyStatusChanged(state); } -void VoiceInteractionControllerClient::NotifySettingsEnabled(bool enabled) { - DCHECK(voice_interaction_controller_); - voice_interaction_controller_->NotifySettingsEnabled(enabled); -} - -void VoiceInteractionControllerClient::NotifyContextEnabled(bool enabled) { - DCHECK(voice_interaction_controller_); - voice_interaction_controller_->NotifyContextEnabled(enabled); -} - -void VoiceInteractionControllerClient::NotifySetupCompleted(bool completed) { - DCHECK(voice_interaction_controller_); - voice_interaction_controller_->NotifySetupCompleted(completed); -} - -void VoiceInteractionControllerClient::NotifyFeatureAllowed( - ash::mojom::AssistantAllowedState state) { - DCHECK(voice_interaction_controller_); - voice_interaction_controller_->NotifyFeatureAllowed(state); -} - void VoiceInteractionControllerClient::SetControllerForTesting( ash::mojom::VoiceInteractionControllerPtr controller) { voice_interaction_controller_ = std::move(controller); @@ -54,6 +69,110 @@ voice_interaction_controller_.FlushForTesting(); } +void VoiceInteractionControllerClient::NotifySettingsEnabled() { + DCHECK(profile_); + PrefService* prefs = profile_->GetPrefs(); + bool enabled = prefs->GetBoolean(prefs::kVoiceInteractionEnabled); + voice_interaction_controller_->NotifySettingsEnabled(enabled); +} + +void VoiceInteractionControllerClient::NotifyContextEnabled() { + DCHECK(profile_); + PrefService* prefs = profile_->GetPrefs(); + bool enabled = prefs->GetBoolean(prefs::kVoiceInteractionContextEnabled); + voice_interaction_controller_->NotifyContextEnabled(enabled); +} + +void VoiceInteractionControllerClient::NotifySetupCompleted() { + DCHECK(profile_); + PrefService* prefs = profile_->GetPrefs(); + bool completed = + prefs->GetBoolean(prefs::kArcVoiceInteractionValuePropAccepted); + voice_interaction_controller_->NotifySetupCompleted(completed); +} + +void VoiceInteractionControllerClient::NotifyFeatureAllowed() { + DCHECK(profile_); + ash::mojom::AssistantAllowedState state = + IsAssistantAllowedForProfile(profile_); + voice_interaction_controller_->NotifyFeatureAllowed(state); +} + +void VoiceInteractionControllerClient::ActiveUserChanged( + const user_manager::User* active_user) { + if (active_user && active_user->is_profile_created()) + SetProfile(ProfileManager::GetActiveUserProfile()); +} + +void VoiceInteractionControllerClient::OnArcPlayStoreEnabledChanged( + bool enabled) { + NotifyFeatureAllowed(); +} + +void VoiceInteractionControllerClient::SetProfile(Profile* profile) { + // Do nothing if this is called for the current profile. This can happen. For + // example, ChromeSessionManager fires both + // NOTIFICATION_LOGIN_USER_PROFILE_PREPARED and NOTIFICATION_SESSION_STARTED, + // and we are observing both events. + if (profile_ == profile) + return; + + profile_ = profile; + pref_change_registrar_.reset(); + + if (!profile_) + return; + + PrefService* prefs = profile->GetPrefs(); + pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>(); + pref_change_registrar_->Init(prefs); + pref_change_registrar_->Add( + prefs::kArcVoiceInteractionValuePropAccepted, + base::BindRepeating( + &VoiceInteractionControllerClient::NotifySetupCompleted, + base::Unretained(this))); + pref_change_registrar_->Add( + prefs::kVoiceInteractionEnabled, + base::BindRepeating( + &VoiceInteractionControllerClient::NotifySettingsEnabled, + base::Unretained(this))); + pref_change_registrar_->Add( + prefs::kVoiceInteractionContextEnabled, + base::BindRepeating( + &VoiceInteractionControllerClient::NotifyContextEnabled, + base::Unretained(this))); + + NotifySetupCompleted(); + NotifySettingsEnabled(); + NotifyContextEnabled(); + NotifyFeatureAllowed(); +} + +void VoiceInteractionControllerClient::Observe( + int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + switch (type) { + case chrome::NOTIFICATION_LOGIN_USER_PROFILE_PREPARED: + // Update |profile_| when login user profile is prepared. + // NOTIFICATION_SESSION_STARTED is not fired from UserSessionManager, but + // profile may be changed by UserSessionManager in OOBE flow. + SetProfile(ProfileManager::GetActiveUserProfile()); + break; + case chrome::NOTIFICATION_SESSION_STARTED: + // Update |profile_| when entering a session. + SetProfile(ProfileManager::GetActiveUserProfile()); + + // Add a session state observer to be able to monitor session changes. + if (!session_state_observer_.get()) { + session_state_observer_ = + std::make_unique<user_manager::ScopedUserSessionStateObserver>( + this); + } + break; + } +} + void VoiceInteractionControllerClient::ConnectToVoiceInteractionController() { content::ServiceManagerConnection* connection = content::ServiceManagerConnection::GetForProcess();
diff --git a/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.h b/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.h index 8103f176..b193130 100644 --- a/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.h +++ b/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.h
@@ -8,22 +8,28 @@ #include <memory> #include "ash/public/interfaces/voice_interaction_controller.mojom.h" +#include "chrome/browser/chromeos/arc/arc_session_manager.h" +#include "components/prefs/pref_change_registrar.h" +#include "components/user_manager/user_manager.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" namespace arc { -// The client of VoiceInteractionController. Can be used to notify the -// controller on ash side about the changes of voice interaction flags. -class VoiceInteractionControllerClient { +// The client of VoiceInteractionController. It monitors various user session +// states and notifies Ash side. It can also be used to notify some specific +// state changes that does not have an observer interface. +class VoiceInteractionControllerClient + : public ArcSessionManager::Observer, + public content::NotificationObserver, + public user_manager::UserManager::UserSessionStateObserver { public: VoiceInteractionControllerClient(); - ~VoiceInteractionControllerClient(); + ~VoiceInteractionControllerClient() override; + static VoiceInteractionControllerClient* Get(); // Notify the controller about state changes. void NotifyStatusChanged(ash::mojom::VoiceInteractionState state); - void NotifySettingsEnabled(bool enabled); - void NotifyContextEnabled(bool enabled); - void NotifySetupCompleted(bool completed); - void NotifyFeatureAllowed(ash::mojom::AssistantAllowedState state); // Testing methods. void SetControllerForTesting( @@ -31,10 +37,38 @@ void FlushMojoForTesting(); private: + friend class VoiceInteractionControllerClientTest; + + // Notify the controller about state changes. + void NotifySettingsEnabled(); + void NotifyContextEnabled(); + void NotifySetupCompleted(); + void NotifyFeatureAllowed(); + + // user_manager::UserManager::UserSessionStateObserver overrides: + void ActiveUserChanged(const user_manager::User* active_user) override; + + // ArcSessionManager::Observer overrides: + void OnArcPlayStoreEnabledChanged(bool enabled) override; + + // content::NotificationObserver: + void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) override; + + void SetProfile(Profile* profile); + void ConnectToVoiceInteractionController(); ash::mojom::VoiceInteractionControllerPtr voice_interaction_controller_; + content::NotificationRegistrar notification_registrar_; + std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_; + std::unique_ptr<user_manager::ScopedUserSessionStateObserver> + session_state_observer_; + + Profile* profile_ = nullptr; + DISALLOW_COPY_AND_ASSIGN(VoiceInteractionControllerClient); };
diff --git a/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client_unittest.cc b/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client_unittest.cc new file mode 100644 index 0000000..a1a79604 --- /dev/null +++ b/chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client_unittest.cc
@@ -0,0 +1,132 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.h" + +#include "ash/shell.h" +#include "ash/test/ash_test_base.h" +#include "base/bind.h" +#include "base/files/scoped_temp_dir.h" +#include "chrome/browser/chromeos/arc/arc_session_manager.h" +#include "chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.h" +#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" +#include "chrome/test/base/testing_profile.h" +#include "components/arc/arc_prefs.h" +#include "components/arc/arc_util.h" +#include "components/arc/test/fake_arc_session.h" +#include "components/prefs/pref_service.h" +#include "components/user_manager/scoped_user_manager.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace arc { + +class VoiceInteractionControllerClientTest : public ash::AshTestBase { + public: + VoiceInteractionControllerClientTest() + : fake_user_manager_( + std::make_unique<chromeos::FakeChromeUserManager>()) {} + ~VoiceInteractionControllerClientTest() override = default; + + void SetUp() override { + AshTestBase::SetUp(); + + // Setup test profile. + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + TestingProfile::Builder profile_builder; + profile_builder.SetProfileName("user@gmail.com"); + profile_builder.SetPath(temp_dir_.GetPath().AppendASCII("TestArcProfile")); + profile_ = profile_builder.Build(); + + // Setup dependencies + arc_session_manager_ = + std::make_unique<ArcSessionManager>(std::make_unique<ArcSessionRunner>( + base::BindRepeating(FakeArcSession::Create))); + const AccountId account_id(AccountId::FromUserEmailGaiaId( + profile()->GetProfileUserName(), "1234567890")); + GetFakeUserManager()->AddUser(account_id); + GetFakeUserManager()->LoginUser(account_id); + + voice_interaction_controller_ = + std::make_unique<FakeVoiceInteractionController>(); + + voice_interaction_controller_client_ = + std::make_unique<VoiceInteractionControllerClient>(); + voice_interaction_controller_client_->SetControllerForTesting( + voice_interaction_controller_->CreateInterfacePtrAndBind()); + voice_interaction_controller_client_->SetProfile(profile_.get()); + } + + void TearDown() override { + arc_session_manager_->Shutdown(); + arc_session_manager_.reset(); + voice_interaction_controller_.reset(); + voice_interaction_controller_client_.reset(); + profile_.reset(); + AshTestBase::TearDown(); + } + + FakeVoiceInteractionController* voice_interaction_controller() { + return voice_interaction_controller_.get(); + } + + VoiceInteractionControllerClient* voice_interaction_controller_client() { + return voice_interaction_controller_client_.get(); + } + + Profile* profile() { return profile_.get(); } + + ArcSessionManager* arc_session_manager() { + return arc_session_manager_.get(); + } + + void FlushVoiceInteractionControllerMojo() { + voice_interaction_controller_client()->FlushMojoForTesting(); + } + + private: + chromeos::FakeChromeUserManager* GetFakeUserManager() const { + return static_cast<chromeos::FakeChromeUserManager*>( + user_manager::UserManager::Get()); + } + + base::ScopedTempDir temp_dir_; + std::unique_ptr<TestingProfile> profile_; + user_manager::ScopedUserManager fake_user_manager_; + std::unique_ptr<ArcSessionManager> arc_session_manager_; + std::unique_ptr<FakeVoiceInteractionController> voice_interaction_controller_; + std::unique_ptr<VoiceInteractionControllerClient> + voice_interaction_controller_client_; +}; + +TEST_F(VoiceInteractionControllerClientTest, PrefChangeSendsNotification) { + PrefService* prefs = profile()->GetPrefs(); + + ASSERT_EQ(false, prefs->GetBoolean(prefs::kVoiceInteractionEnabled)); + prefs->SetBoolean(prefs::kVoiceInteractionEnabled, true); + ASSERT_EQ(true, prefs->GetBoolean(prefs::kVoiceInteractionEnabled)); + voice_interaction_controller_client()->FlushMojoForTesting(); + EXPECT_EQ( + true, + voice_interaction_controller()->voice_interaction_settings_enabled()); + + ASSERT_EQ(false, prefs->GetBoolean(prefs::kVoiceInteractionContextEnabled)); + prefs->SetBoolean(prefs::kVoiceInteractionContextEnabled, true); + ASSERT_EQ(true, prefs->GetBoolean(prefs::kVoiceInteractionContextEnabled)); + voice_interaction_controller_client()->FlushMojoForTesting(); + EXPECT_EQ( + true, + voice_interaction_controller()->voice_interaction_context_enabled()); + + ASSERT_EQ(false, + prefs->GetBoolean(prefs::kArcVoiceInteractionValuePropAccepted)); + prefs->SetBoolean(prefs::kArcVoiceInteractionValuePropAccepted, true); + ASSERT_EQ(true, + prefs->GetBoolean(prefs::kArcVoiceInteractionValuePropAccepted)); + voice_interaction_controller_client()->FlushMojoForTesting(); + EXPECT_EQ( + true, + voice_interaction_controller()->voice_interaction_setup_completed()); +} + +} // namespace arc
diff --git a/chrome/browser/chromeos/attestation/attestation_policy_observer.cc b/chrome/browser/chromeos/attestation/attestation_policy_observer.cc index 8e9a437..e692884 100644 --- a/chrome/browser/chromeos/attestation/attestation_policy_observer.cc +++ b/chrome/browser/chromeos/attestation/attestation_policy_observer.cc
@@ -87,6 +87,23 @@ on_success.Run(result->data); } +void DBusPrivacyCACallback( + const base::RepeatingCallback<void(const std::string&)> on_success, + const base::RepeatingCallback< + void(chromeos::attestation::AttestationStatus)> on_failure, + const base::Location& from_here, + chromeos::attestation::AttestationStatus status, + const std::string& data) { + if (status == chromeos::attestation::ATTESTATION_SUCCESS) { + on_success.Run(data); + return; + } + LOG(ERROR) << "Cryptohome DBus method or server called failed with status:" + << status << ": " << from_here.ToString(); + if (!on_failure.is_null()) + on_failure.Run(status); +} + } // namespace namespace chromeos { @@ -96,9 +113,10 @@ policy::CloudPolicyClient* policy_client) : cros_settings_(CrosSettings::Get()), policy_client_(policy_client), - cryptohome_client_(NULL), - attestation_flow_(NULL), + cryptohome_client_(nullptr), + attestation_flow_(nullptr), num_retries_(0), + retry_limit_(kRetryLimit), retry_delay_(kRetryDelay), weak_factory_(this) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -188,17 +206,18 @@ std::string(), // Not used. true, // Force a new key to be generated. base::Bind( - [](const base::Callback<void(const std::string&)> on_success, - const base::Closure& on_failure, const base::Location& from_here, - bool success, const std::string& data) { - DBusStringCallback(on_success, on_failure, from_here, - CryptohomeClient::TpmAttestationDataResult{ - success, std::move(data)}); + [](const base::RepeatingCallback<void(const std::string&)> on_success, + const base::RepeatingCallback<void(AttestationStatus)> on_failure, + const base::Location& from_here, AttestationStatus status, + const std::string& data) { + DBusPrivacyCACallback(on_success, on_failure, from_here, status, + std::move(data)); }, - base::Bind(&AttestationPolicyObserver::UploadCertificate, - weak_factory_.GetWeakPtr()), - base::Bind(&AttestationPolicyObserver::Reschedule, - weak_factory_.GetWeakPtr()), + base::BindRepeating(&AttestationPolicyObserver::UploadCertificate, + weak_factory_.GetWeakPtr()), + base::BindRepeating( + &AttestationPolicyObserver::HandleGetCertificateFailure, + weak_factory_.GetWeakPtr()), FROM_HERE)); } @@ -307,16 +326,23 @@ KEY_DEVICE, cryptohome::Identification(), // Not used. kEnterpriseMachineKey, new_payload, - base::BindOnce(DBusBoolRedirectCallback, base::Closure(), base::Closure(), - base::Closure(), FROM_HERE)); + base::BindRepeating(DBusBoolRedirectCallback, base::RepeatingClosure(), + base::RepeatingClosure(), base::RepeatingClosure(), + FROM_HERE)); +} + +void AttestationPolicyObserver::HandleGetCertificateFailure( + AttestationStatus status) { + if (status != ATTESTATION_SERVER_BAD_REQUEST_FAILURE) + Reschedule(); } void AttestationPolicyObserver::Reschedule() { - if (++num_retries_ < kRetryLimit) { + if (++num_retries_ < retry_limit_) { content::BrowserThread::PostDelayedTask( content::BrowserThread::UI, FROM_HERE, - base::BindOnce(&AttestationPolicyObserver::Start, - weak_factory_.GetWeakPtr()), + base::BindRepeating(&AttestationPolicyObserver::Start, + weak_factory_.GetWeakPtr()), base::TimeDelta::FromSeconds(retry_delay_)); } else { LOG(WARNING) << "AttestationPolicyObserver: Retry limit exceeded.";
diff --git a/chrome/browser/chromeos/attestation/attestation_policy_observer.h b/chrome/browser/chromeos/attestation/attestation_policy_observer.h index c61da96..00c1053 100644 --- a/chrome/browser/chromeos/attestation/attestation_policy_observer.h +++ b/chrome/browser/chromeos/attestation/attestation_policy_observer.h
@@ -12,6 +12,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/chromeos/settings/cros_settings.h" +#include "chromeos/attestation/attestation_constants.h" namespace policy { class CloudPolicyClient; @@ -45,10 +46,10 @@ ~AttestationPolicyObserver(); + // Sets the retry limit in number of tries; useful in testing. + void set_retry_limit(int limit) { retry_limit_ = limit; } // Sets the retry delay in seconds; useful in testing. - void set_retry_delay(int retry_delay) { - retry_delay_ = retry_delay; - } + void set_retry_delay(int retry_delay) { retry_delay_ = retry_delay; } private: // Called when the attestation setting changes. @@ -84,6 +85,9 @@ // Marks a key as uploaded in the payload proto. void MarkAsUploaded(const std::string& key_payload); + // Handles failure of getting a certificate. + void HandleGetCertificateFailure(AttestationStatus status); + // Reschedules a policy check (i.e. a call to Start) for a later time. // TODO(dkrahn): A better solution would be to wait for a dbus signal which // indicates the system is ready to process this task. See crbug.com/256845. @@ -95,6 +99,7 @@ AttestationFlow* attestation_flow_; std::unique_ptr<AttestationFlow> default_attestation_flow_; int num_retries_; + int retry_limit_; int retry_delay_; std::unique_ptr<CrosSettings::ObserverSubscription> attestation_subscription_;
diff --git a/chrome/browser/chromeos/attestation/attestation_policy_observer_unittest.cc b/chrome/browser/chromeos/attestation/attestation_policy_observer_unittest.cc index 0509852a..40042e6c 100644 --- a/chrome/browser/chromeos/attestation/attestation_policy_observer_unittest.cc +++ b/chrome/browser/chromeos/attestation/attestation_policy_observer_unittest.cc
@@ -39,7 +39,20 @@ void CertCallbackSuccess(const AttestationFlow::CertificateCallback& callback) { base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(callback, true, "fake_cert")); + FROM_HERE, base::BindOnce(callback, ATTESTATION_SUCCESS, "fake_cert")); +} + +void CertCallbackUnspecifiedFailure( + const AttestationFlow::CertificateCallback& callback) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(callback, ATTESTATION_UNSPECIFIED_FAILURE, "")); +} + +void CertCallbackBadRequestFailure( + const AttestationFlow::CertificateCallback& callback) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(callback, ATTESTATION_SERVER_BAD_REQUEST_FAILURE, "")); } void StatusCallbackSuccess( @@ -105,6 +118,7 @@ AttestationPolicyObserver observer(&policy_client_, &cryptohome_client_, &attestation_flow_); + observer.set_retry_limit(3); observer.set_retry_delay(0); base::RunLoop().RunUntilIdle(); } @@ -134,6 +148,18 @@ Run(); } +TEST_F(AttestationPolicyObserverTest, GetCertificateUnspecifiedFailure) { + EXPECT_CALL(attestation_flow_, GetCertificate(_, _, _, _, _)) + .WillRepeatedly(WithArgs<4>(Invoke(CertCallbackUnspecifiedFailure))); + Run(); +} + +TEST_F(AttestationPolicyObserverTest, GetCertificateBadRequestFailure) { + EXPECT_CALL(attestation_flow_, GetCertificate(_, _, _, _, _)) + .WillOnce(WithArgs<4>(Invoke(CertCallbackBadRequestFailure))); + Run(); +} + TEST_F(AttestationPolicyObserverTest, NewCertificate) { SetupMocks(MOCK_NEW_KEY, ""); Run();
diff --git a/chrome/browser/chromeos/attestation/enrollment_policy_observer.cc b/chrome/browser/chromeos/attestation/enrollment_policy_observer.cc index 9955fb7..02d4d2b 100644 --- a/chrome/browser/chromeos/attestation/enrollment_policy_observer.cc +++ b/chrome/browser/chromeos/attestation/enrollment_policy_observer.cc
@@ -35,25 +35,21 @@ const int kRetryDelay = 5; // Seconds. const int kRetryLimit = 100; -// A dbus callback which handles a string result. -// -// Parameters -// on_success - Called when status=success and result=true. -// status - The dbus operation status. -// result - The result returned by the dbus operation. -// data - The data returned by the dbus operation. -void DBusStringCallback( - const base::Callback<void(const std::string&)> on_success, - const base::Closure& on_failure, +void DBusPrivacyCACallback( + const base::RepeatingCallback<void(const std::string&)> on_success, + const base::RepeatingCallback< + void(chromeos::attestation::AttestationStatus)> on_failure, const base::Location& from_here, - const chromeos::CryptohomeClient::TpmAttestationDataResult& result) { - if (!result.success) { - LOG(ERROR) << "Cryptohome DBus method failed: " << from_here.ToString(); - if (!on_failure.is_null()) - on_failure.Run(); + chromeos::attestation::AttestationStatus status, + const std::string& data) { + if (status == chromeos::attestation::ATTESTATION_SUCCESS) { + on_success.Run(data); return; } - on_success.Run(result.data); + LOG(ERROR) << "Cryptohome DBus method or server call failed with status: " + << status << ": " << from_here.ToString(); + if (!on_failure.is_null()) + on_failure.Run(status); } } // namespace @@ -63,26 +59,25 @@ EnrollmentPolicyObserver::EnrollmentPolicyObserver( policy::CloudPolicyClient* policy_client) - : cros_settings_(CrosSettings::Get()), + : device_settings_service_(DeviceSettingsService::Get()), policy_client_(policy_client), - cryptohome_client_(NULL), - attestation_flow_(NULL), + cryptohome_client_(nullptr), + attestation_flow_(nullptr), num_retries_(0), + retry_limit_(kRetryLimit), retry_delay_(kRetryDelay), weak_factory_(this) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - attestation_subscription_ = cros_settings_->AddSettingsObserver( - kDeviceEnrollmentIdNeeded, - base::Bind(&EnrollmentPolicyObserver::EnrollmentSettingChanged, - base::Unretained(this))); + device_settings_service_->AddObserver(this); Start(); } EnrollmentPolicyObserver::EnrollmentPolicyObserver( policy::CloudPolicyClient* policy_client, + DeviceSettingsService* device_settings_service, CryptohomeClient* cryptohome_client, AttestationFlow* attestation_flow) - : cros_settings_(CrosSettings::Get()), + : device_settings_service_(device_settings_service), policy_client_(policy_client), cryptohome_client_(cryptohome_client), attestation_flow_(attestation_flow), @@ -90,28 +85,28 @@ retry_delay_(kRetryDelay), weak_factory_(this) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - attestation_subscription_ = cros_settings_->AddSettingsObserver( - kDeviceEnrollmentIdNeeded, - base::Bind(&EnrollmentPolicyObserver::EnrollmentSettingChanged, - base::Unretained(this))); + + device_settings_service_->AddObserver(this); Start(); } EnrollmentPolicyObserver::~EnrollmentPolicyObserver() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK(DeviceSettingsService::IsInitialized()); + device_settings_service_->RemoveObserver(this); } -void EnrollmentPolicyObserver::EnrollmentSettingChanged() { +void EnrollmentPolicyObserver::DeviceSettingsUpdated() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); num_retries_ = 0; Start(); } void EnrollmentPolicyObserver::Start() { - // If we identification for enrollment isn't needed, there is nothing to do. - bool needed = false; - if (!cros_settings_->GetBoolean(kDeviceEnrollmentIdNeeded, &needed) || - !needed) + // If identification for enrollment isn't needed, there is nothing to do. + const enterprise_management::PolicyData* policy_data = + device_settings_service_->policy_data(); + if (!policy_data || !policy_data->enrollment_id_needed()) return; // We expect a registered CloudPolicyClient. @@ -143,17 +138,19 @@ std::string(), // Not used. false, // Not used. base::Bind( - [](const base::Callback<void(const std::string&)> on_success, - const base::Closure& on_failure, const base::Location& from_here, - bool success, const std::string& data) { - DBusStringCallback(on_success, on_failure, from_here, - CryptohomeClient::TpmAttestationDataResult{ - success, std::move(data)}); + [](const base::RepeatingCallback<void(const std::string&)> on_success, + const base::RepeatingCallback<void( + chromeos::attestation::AttestationStatus)> on_failure, + const base::Location& from_here, AttestationStatus status, + const std::string& data) { + DBusPrivacyCACallback(on_success, on_failure, from_here, status, + std::move(data)); }, - base::Bind(&EnrollmentPolicyObserver::UploadCertificate, - weak_factory_.GetWeakPtr()), - base::Bind(&EnrollmentPolicyObserver::Reschedule, - weak_factory_.GetWeakPtr()), + base::BindRepeating(&EnrollmentPolicyObserver::UploadCertificate, + weak_factory_.GetWeakPtr()), + base::BindRepeating( + &EnrollmentPolicyObserver::HandleGetCertificateFailure, + weak_factory_.GetWeakPtr()), FROM_HERE)); } @@ -169,11 +166,14 @@ if (!status) return; VLOG(1) << "Enterprise Enrollment Certificate uploaded to DMServer."; - cros_settings_->SetBoolean(kDeviceEnrollmentIdNeeded, false); } -void EnrollmentPolicyObserver::Reschedule() { - if (++num_retries_ < kRetryLimit) { +void EnrollmentPolicyObserver::HandleGetCertificateFailure( + AttestationStatus status) { + if (status == ATTESTATION_SERVER_BAD_REQUEST_FAILURE) { + // We cannot get an enrollment cert (no EID) so upload an empty one. + UploadCertificate(""); + } else if (++num_retries_ < retry_limit_) { content::BrowserThread::PostDelayedTask( content::BrowserThread::UI, FROM_HERE, base::BindOnce(&EnrollmentPolicyObserver::Start,
diff --git a/chrome/browser/chromeos/attestation/enrollment_policy_observer.h b/chrome/browser/chromeos/attestation/enrollment_policy_observer.h index 439478be..e068720 100644 --- a/chrome/browser/chromeos/attestation/enrollment_policy_observer.h +++ b/chrome/browser/chromeos/attestation/enrollment_policy_observer.h
@@ -11,7 +11,8 @@ #include "base/callback.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "chrome/browser/chromeos/settings/cros_settings.h" +#include "chrome/browser/chromeos/settings/device_settings_service.h" +#include "chromeos/attestation/attestation_constants.h" namespace policy { class CloudPolicyClient; @@ -19,7 +20,6 @@ namespace chromeos { -class CrosSettings; class CryptohomeClient; namespace attestation { @@ -28,28 +28,30 @@ // A class which observes policy changes and triggers uploading identification // for enrollment if necessary. -class EnrollmentPolicyObserver { +class EnrollmentPolicyObserver : public DeviceSettingsService::Observer { public: - // The observer immediately connects with CrosSettings to listen for policy - // changes. The CloudPolicyClient is used to upload data to the server; it - // must be in the registered state. This class does not take ownership of - // |policy_client|. + // The observer immediately connects with DeviceSettingsService to listen for + // policy changes. The CloudPolicyClient is used to upload data to the + // server; it must be in the registered state. This class does not take + // ownership of |policy_client|. explicit EnrollmentPolicyObserver(policy::CloudPolicyClient* policy_client); - // A constructor which allows custom CryptohomeClient and AttestationFlow - // implementations. Useful for testing. + // A constructor which accepts custom instances useful for testing. EnrollmentPolicyObserver(policy::CloudPolicyClient* policy_client, + DeviceSettingsService* device_settings_service, CryptohomeClient* cryptohome_client, AttestationFlow* attestation_flow); - ~EnrollmentPolicyObserver(); + ~EnrollmentPolicyObserver() override; + // Sets the retry limit in number of tries; useful in testing. + void set_retry_limit(int limit) { retry_limit_ = limit; } // Sets the retry delay in seconds; useful in testing. void set_retry_delay(int retry_delay) { retry_delay_ = retry_delay; } private: - // Called when the enrollment setting changes. - void EnrollmentSettingChanged(); + // Called when the device settings change. + void DeviceSettingsUpdated() override; // Checks enrollment setting and starts any necessary work. void Start(); @@ -64,25 +66,24 @@ // will be true. void OnUploadComplete(bool status); - // Reschedules a policy check (i.e. a call to Start) for a later time. - // TODO(crbug.com/256845): A better solution would be to wait for a DBUS - // signal which indicates the system is ready to process this task. - void Reschedule(); + // Handles a failure to get a certificate. + void HandleGetCertificateFailure(AttestationStatus status); - CrosSettings* cros_settings_; + DeviceSettingsService* device_settings_service_; policy::CloudPolicyClient* policy_client_; CryptohomeClient* cryptohome_client_; AttestationFlow* attestation_flow_; std::unique_ptr<AttestationFlow> default_attestation_flow_; int num_retries_; + int retry_limit_; int retry_delay_; - std::unique_ptr<CrosSettings::ObserverSubscription> attestation_subscription_; - // Note: This should remain the last member so it'll be destroyed and // invalidate the weak pointers before any other members are destroyed. base::WeakPtrFactory<EnrollmentPolicyObserver> weak_factory_; + friend class EnrollmentPolicyObserverTest; + DISALLOW_COPY_AND_ASSIGN(EnrollmentPolicyObserver); };
diff --git a/chrome/browser/chromeos/attestation/enrollment_policy_observer_unittest.cc b/chrome/browser/chromeos/attestation/enrollment_policy_observer_unittest.cc index ba884865..c6ca185 100644 --- a/chrome/browser/chromeos/attestation/enrollment_policy_observer_unittest.cc +++ b/chrome/browser/chromeos/attestation/enrollment_policy_observer_unittest.cc
@@ -13,16 +13,16 @@ #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/chromeos/attestation/enrollment_policy_observer.h" -#include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h" +#include "chrome/browser/chromeos/settings/device_settings_test_helper.h" #include "chromeos/attestation/mock_attestation_flow.h" #include "chromeos/dbus/fake_cryptohome_client.h" #include "chromeos/settings/cros_settings_names.h" #include "components/policy/core/common/cloud/mock_cloud_policy_client.h" -#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" using testing::_; using testing::Invoke; +using testing::Return; using testing::StrictMock; using testing::WithArgs; @@ -33,7 +33,20 @@ void CertCallbackSuccess(const AttestationFlow::CertificateCallback& callback) { base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(callback, true, "fake_cert")); + FROM_HERE, base::BindOnce(callback, ATTESTATION_SUCCESS, "fake_cert")); +} + +void CertCallbackUnspecifiedFailure( + const AttestationFlow::CertificateCallback& callback) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(callback, ATTESTATION_UNSPECIFIED_FAILURE, "")); +} + +void CertCallbackBadRequestFailure( + const AttestationFlow::CertificateCallback& callback) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(callback, ATTESTATION_SERVER_BAD_REQUEST_FAILURE, "")); } void StatusCallbackSuccess( @@ -44,40 +57,52 @@ } // namespace -class EnrollmentPolicyObserverTest : public ::testing::Test { +class EnrollmentPolicyObserverTest : public DeviceSettingsTestBase { public: EnrollmentPolicyObserverTest() { - settings_helper_.ReplaceProvider(kDeviceEnrollmentIdNeeded); - settings_helper_.SetBoolean(kDeviceEnrollmentIdNeeded, true); policy_client_.SetDMToken("fake_dm_token"); } protected: - // Configures mock expectations when identification for enrollment is needed. - void SetupMocks() { - EXPECT_CALL(attestation_flow_, GetCertificate(_, _, _, _, _)) - .WillOnce(WithArgs<4>(Invoke(CertCallbackSuccess))); - EXPECT_CALL(policy_client_, - UploadEnterpriseEnrollmentCertificate("fake_cert", _)) - .WillOnce(WithArgs<1>(Invoke(StatusCallbackSuccess))); + void SetUpEnrollmentIdNeeded(bool enrollment_id_needed) { + if (enrollment_id_needed) { + EXPECT_CALL(attestation_flow_, GetCertificate(_, _, _, _, _)) + .WillOnce(WithArgs<4>(Invoke(CertCallbackSuccess))); + EXPECT_CALL(policy_client_, + UploadEnterpriseEnrollmentCertificate("fake_cert", _)) + .WillOnce(WithArgs<1>(Invoke(StatusCallbackSuccess))); + } + SetUpDevicePolicy(enrollment_id_needed); + } + + void SetUpDevicePolicy(bool enrollment_id_needed) { + device_policy_.policy_data().set_enrollment_id_needed(enrollment_id_needed); + device_policy_.Build(); + session_manager_client_.set_device_policy(device_policy_.GetBlob()); + ReloadDeviceSettings(); } void Run() { - EnrollmentPolicyObserver observer(&policy_client_, &cryptohome_client_, - &attestation_flow_); + EnrollmentPolicyObserver observer(&policy_client_, + &device_settings_service_, + &cryptohome_client_, &attestation_flow_); + observer.set_retry_limit(3); observer.set_retry_delay(0); base::RunLoop().RunUntilIdle(); } - content::TestBrowserThreadBundle test_browser_thread_bundle_; - ScopedCrosSettingsTestHelper settings_helper_; FakeCryptohomeClient cryptohome_client_; StrictMock<MockAttestationFlow> attestation_flow_; StrictMock<policy::MockCloudPolicyClient> policy_client_; }; +TEST_F(EnrollmentPolicyObserverTest, UploadEnterpriseEnrollmentCertificate) { + SetUpEnrollmentIdNeeded(true); + Run(); +} + TEST_F(EnrollmentPolicyObserverTest, FeatureDisabled) { - settings_helper_.SetBoolean(kDeviceEnrollmentIdNeeded, false); + SetUpEnrollmentIdNeeded(false); Run(); } @@ -86,8 +111,25 @@ Run(); } +TEST_F(EnrollmentPolicyObserverTest, GetCertificateUnspecifiedFailure) { + EXPECT_CALL(attestation_flow_, GetCertificate(_, _, _, _, _)) + .WillRepeatedly(WithArgs<4>(Invoke(CertCallbackUnspecifiedFailure))); + SetUpDevicePolicy(true); + Run(); +} + +TEST_F(EnrollmentPolicyObserverTest, GetCertificateBadRequestFailure) { + EXPECT_CALL(attestation_flow_, GetCertificate(_, _, _, _, _)) + .WillOnce(WithArgs<4>(Invoke(CertCallbackBadRequestFailure))); + EXPECT_CALL(policy_client_, UploadEnterpriseEnrollmentCertificate("", _)) + .WillOnce(WithArgs<1>(Invoke(StatusCallbackSuccess))); + SetUpDevicePolicy(true); + Run(); +} + TEST_F(EnrollmentPolicyObserverTest, DBusFailureRetry) { - SetupMocks(); + SetUpEnrollmentIdNeeded(true); + // Simulate a DBus failure. cryptohome_client_.SetServiceIsAvailable(false);
diff --git a/chrome/browser/chromeos/attestation/platform_verification_flow.cc b/chrome/browser/chromeos/attestation/platform_verification_flow.cc index 4d4f2b1d..c952392 100644 --- a/chrome/browser/chromeos/attestation/platform_verification_flow.cc +++ b/chrome/browser/chromeos/attestation/platform_verification_flow.cc
@@ -283,11 +283,11 @@ const ChallengeContext& context, const AccountId& account_id, std::unique_ptr<base::Timer> timer, - bool operation_success, + AttestationStatus operation_status, const std::string& certificate_chain) { // Log failure before checking the timer so all failures are logged, even if // they took too long. - if (!operation_success) { + if (operation_status != ATTESTATION_SUCCESS) { LOG(WARNING) << "PlatformVerificationFlow: Failed to certify platform."; } if (!timer->IsRunning()) { @@ -296,7 +296,7 @@ return; } timer->Stop(); - if (!operation_success) { + if (operation_status != ATTESTATION_SUCCESS) { ReportError(context.callback, PLATFORM_NOT_VERIFIED); return; } @@ -422,10 +422,10 @@ void PlatformVerificationFlow::RenewCertificateCallback( const std::string& old_certificate_chain, - bool operation_success, + AttestationStatus operation_status, const std::string& certificate_chain) { renewals_in_progress_.erase(old_certificate_chain); - if (!operation_success) { + if (operation_status != ATTESTATION_SUCCESS) { LOG(WARNING) << "PlatformVerificationFlow: Failed to renew platform " "certificate."; return;
diff --git a/chrome/browser/chromeos/attestation/platform_verification_flow.h b/chrome/browser/chromeos/attestation/platform_verification_flow.h index be975d42..85dfebe 100644 --- a/chrome/browser/chromeos/attestation/platform_verification_flow.h +++ b/chrome/browser/chromeos/attestation/platform_verification_flow.h
@@ -14,6 +14,7 @@ #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "base/timer/timer.h" +#include "chromeos/attestation/attestation_constants.h" #include "url/gurl.h" class AccountId; @@ -199,7 +200,7 @@ void OnCertificateReady(const ChallengeContext& context, const AccountId& account_id, std::unique_ptr<base::Timer> timer, - bool operation_success, + AttestationStatus operation_status, const std::string& certificate_chain); // A callback run after a constant delay to handle timeouts for lengthy @@ -233,7 +234,7 @@ // An AttestationFlow::CertificateCallback that handles renewal completion. // |old_certificate_chain| contains the chain that has been replaced. void RenewCertificateCallback(const std::string& old_certificate_chain, - bool operation_success, + AttestationStatus operation_status, const std::string& certificate_chain); AttestationFlow* attestation_flow_;
diff --git a/chrome/browser/chromeos/attestation/platform_verification_flow_unittest.cc b/chrome/browser/chromeos/attestation/platform_verification_flow_unittest.cc index ee23961..7f253e3 100644 --- a/chrome/browser/chromeos/attestation/platform_verification_flow_unittest.cc +++ b/chrome/browser/chromeos/attestation/platform_verification_flow_unittest.cc
@@ -98,7 +98,7 @@ class PlatformVerificationFlowTest : public ::testing::Test { public: PlatformVerificationFlowTest() - : certificate_success_(true), + : certificate_status_(ATTESTATION_SUCCESS), fake_certificate_index_(0), sign_challenge_success_(true), result_(PlatformVerificationFlow::INTERNAL_ERROR) {} @@ -148,7 +148,7 @@ (fake_certificate_index_ < fake_certificate_list_.size()) ? fake_certificate_list_[fake_certificate_index_] : kTestCertificate; base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(callback, certificate_success_, certificate)); + FROM_HERE, base::BindOnce(callback, certificate_status_, certificate)); ++fake_certificate_index_; } @@ -188,7 +188,7 @@ scoped_refptr<PlatformVerificationFlow> verifier_; // Controls result of FakeGetCertificate. - bool certificate_success_; + AttestationStatus certificate_status_; std::vector<std::string> fake_certificate_list_; size_t fake_certificate_index_; @@ -227,8 +227,16 @@ EXPECT_EQ(PlatformVerificationFlow::POLICY_REJECTED, result_); } -TEST_F(PlatformVerificationFlowTest, NotVerified) { - certificate_success_ = false; +TEST_F(PlatformVerificationFlowTest, NotVerifiedDueToUnspeciedFailure) { + certificate_status_ = ATTESTATION_UNSPECIFIED_FAILURE; + ExpectAttestationFlow(); + verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(PlatformVerificationFlow::PLATFORM_NOT_VERIFIED, result_); +} + +TEST_F(PlatformVerificationFlowTest, NotVerifiedDueToBadRequestFailure) { + certificate_status_ = ATTESTATION_SERVER_BAD_REQUEST_FAILURE; ExpectAttestationFlow(); verifier_->ChallengePlatformKey(NULL, kTestID, kTestChallenge, callback_); base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.cc b/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.cc index 4c521411..5e1932d 100644 --- a/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.cc +++ b/chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.cc
@@ -172,8 +172,11 @@ is_get_status_in_progress_ = true; rerun_get_status_on_error_ = false; scheduled_get_user_status_call_.Cancel(); + authpolicy::GetUserStatusRequest request; + request.set_user_principal_name(account_id_.GetUserEmail()); + request.set_account_id(account_id_.GetObjGuid()); chromeos::DBusThreadManager::Get()->GetAuthPolicyClient()->GetUserStatus( - account_id_.GetObjGuid(), + request, base::BindOnce(&AuthPolicyCredentialsManager::OnGetUserStatusCallback, weak_factory_.GetWeakPtr())); }
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index 5f48758..79de5af 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -45,6 +45,7 @@ #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" #include "chrome/browser/chromeos/app_mode/kiosk_mode_idle_app_name_notification.h" #include "chrome/browser/chromeos/arc/arc_service_launcher.h" +#include "chrome/browser/chromeos/arc/voice_interaction/voice_interaction_controller_client.h" #include "chrome/browser/chromeos/ash_config.h" #include "chrome/browser/chromeos/boot_times_recorder.h" #include "chrome/browser/chromeos/dbus/chrome_component_updater_service_provider_delegate.h" @@ -749,6 +750,8 @@ new NetworkThrottlingObserver(g_browser_process->local_state())); arc_service_launcher_ = base::MakeUnique<arc::ArcServiceLauncher>(); + arc_voice_interaction_controller_client_ = + std::make_unique<arc::VoiceInteractionControllerClient>(); chromeos::ResourceReporter::GetInstance()->StartMonitoring( task_manager::TaskManagerInterface::GetTaskManager()); @@ -1132,6 +1135,8 @@ arc_service_launcher_->Shutdown(); + arc_voice_interaction_controller_client_.reset(); + // Unregister CrosSettings observers before CrosSettings is destroyed. shutdown_policy_forwarder_.reset();
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.h b/chrome/browser/chromeos/chrome_browser_main_chromeos.h index ca1c932..f70a0cd 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.h +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.h
@@ -25,6 +25,7 @@ namespace arc { class ArcServiceLauncher; +class VoiceInteractionControllerClient; } namespace chromeos { @@ -112,6 +113,9 @@ std::unique_ptr<arc::ArcServiceLauncher> arc_service_launcher_; + std::unique_ptr<arc::VoiceInteractionControllerClient> + arc_voice_interaction_controller_client_; + std::unique_ptr<LowDiskNotification> low_disk_notification_; std::unique_ptr<ArcKioskAppManager> arc_kiosk_app_manager_;
diff --git a/chrome/browser/chromeos/display/display_preferences.cc b/chrome/browser/chromeos/display/display_preferences.cc index 0d5dab6..3fca1c5 100644 --- a/chrome/browser/chromeos/display/display_preferences.cc +++ b/chrome/browser/chromeos/display/display_preferences.cc
@@ -338,6 +338,28 @@ touch_associations); } +// Loads mirror info for each external display, the info will later be used to +// restore mirror mode. +void LoadExternalDisplayMirrorInfo() { + PrefService* local_state = g_browser_process->local_state(); + const base::ListValue* pref_data = + local_state->GetList(prefs::kExternalDisplayMirrorInfo); + std::set<int64_t> external_display_mirror_info; + for (auto it = pref_data->begin(); it != pref_data->end(); ++it) { + std::string display_id_str; + if (!it->GetAsString(&display_id_str)) + continue; + + int64_t display_id; + if (!base::StringToInt64(display_id_str, &display_id)) + continue; + + external_display_mirror_info.emplace(display_id); + } + GetDisplayManager()->set_external_display_mirror_info( + external_display_mirror_info); +} + void StoreDisplayLayoutPref(const display::DisplayIdList& list, const display::DisplayLayout& display_layout) { DCHECK(display::DisplayLayout::Validate(list, display_layout)); @@ -534,6 +556,18 @@ } } +// Stores mirror info for each external display. +void StoreExternalDisplayMirrorInfo() { + PrefService* local_state = g_browser_process->local_state(); + ListPrefUpdate update(local_state, prefs::kExternalDisplayMirrorInfo); + base::ListValue* pref_data = update.Get(); + pref_data->Clear(); + const std::set<int64_t>& external_display_mirror_info = + GetDisplayManager()->external_display_mirror_info(); + for (const auto& id : external_display_mirror_info) + pref_data->GetList().emplace_back(base::Value(base::Int64ToString(id))); +} + } // namespace void RegisterDisplayLocalStatePrefs(PrefRegistrySimple* registry) { @@ -545,6 +579,7 @@ registry->RegisterStringPref(prefs::kDisplayPowerState, iter->second); registry->RegisterDictionaryPref(prefs::kDisplayRotationLock); registry->RegisterDictionaryPref(prefs::kDisplayTouchAssociations); + registry->RegisterListPref(prefs::kExternalDisplayMirrorInfo); } void StoreDisplayPrefs() { @@ -563,6 +598,7 @@ StoreCurrentDisplayLayoutPrefs(); StoreCurrentDisplayProperties(); StoreDisplayTouchAssociations(); + StoreExternalDisplayMirrorInfo(); } void StoreDisplayRotationPrefs(bool rotation_lock) { @@ -583,6 +619,7 @@ void LoadDisplayPreferences(bool first_run_after_boot) { LoadDisplayLayouts(); LoadDisplayProperties(); + LoadExternalDisplayMirrorInfo(); LoadDisplayRotationState(); LoadDisplayTouchAssociations(); if (!first_run_after_boot) {
diff --git a/chrome/browser/chromeos/display/display_preferences_unittest.cc b/chrome/browser/chromeos/display/display_preferences_unittest.cc index 2ab305c..53483ed 100644 --- a/chrome/browser/chromeos/display/display_preferences_unittest.cc +++ b/chrome/browser/chromeos/display/display_preferences_unittest.cc
@@ -17,6 +17,7 @@ #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" +#include "base/command_line.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" @@ -30,6 +31,7 @@ #include "components/prefs/testing_pref_service.h" #include "components/user_manager/scoped_user_manager.h" #include "ui/display/display_layout_builder.h" +#include "ui/display/display_switches.h" #include "ui/display/manager/chromeos/display_configurator.h" #include "ui/display/manager/chromeos/test/touch_device_manager_test_api.h" #include "ui/display/manager/display_layout_store.h" @@ -227,6 +229,15 @@ pref_data->SetInteger("orientation", static_cast<int>(rotation)); } + void StoreExternalDisplayMirrorInfo( + const std::set<int64_t>& external_display_mirror_info) { + ListPrefUpdate update(local_state(), prefs::kExternalDisplayMirrorInfo); + base::ListValue* pref_data = update.Get(); + pref_data->Clear(); + for (const auto& id : external_display_mirror_info) + pref_data->GetList().emplace_back(base::Value(base::Int64ToString(id))); + } + std::string GetRegisteredDisplayPlacementStr( const display::DisplayIdList& list) { return ash::Shell::Get() @@ -290,11 +301,13 @@ TEST_F(DisplayPreferencesTest, BasicStores) { ash::WindowTreeHostManager* window_tree_host_manager = ash::Shell::Get()->window_tree_host_manager(); - - UpdateDisplay("200x200*2, 400x300#400x400|300x200*1.25"); int64_t id1 = display::Screen::GetScreen()->GetPrimaryDisplay().id(); + + // For each configuration change, we store mirror info only for external + // displays. So set internal display first before adding display. display::test::ScopedSetInternalDisplayId set_internal(display_manager(), id1); + UpdateDisplay("200x200*2, 400x300#400x400|300x200*1.25"); int64_t id2 = display_manager()->GetSecondaryDisplay().id(); int64_t dummy_id = id2 + 1; ASSERT_NE(id1, dummy_id); @@ -375,6 +388,10 @@ EXPECT_TRUE(layout_value->GetBoolean(kMirroredKey, &mirrored)); EXPECT_FALSE(mirrored); + const base::ListValue* external_display_mirror_info = + local_state()->GetList(prefs::kExternalDisplayMirrorInfo); + EXPECT_EQ(0U, external_display_mirror_info->GetSize()); + const base::DictionaryValue* properties = local_state()->GetDictionary(prefs::kDisplayProperties); const base::DictionaryValue* property = nullptr; @@ -519,6 +536,12 @@ EXPECT_FALSE(property->GetInteger("width", &width)); EXPECT_FALSE(property->GetInteger("height", &height)); + external_display_mirror_info = + local_state()->GetList(prefs::kExternalDisplayMirrorInfo); + EXPECT_EQ(1U, external_display_mirror_info->GetSize()); + EXPECT_EQ(base::Int64ToString(id2), + external_display_mirror_info->GetList()[0].GetString()); + // External display's selected resolution must not change // by mirroring. EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id2), &property)); @@ -1057,41 +1080,71 @@ } TEST_F(DisplayPreferencesTest, RestoreUnifiedMode) { - int64_t id1 = display::Screen::GetScreen()->GetPrimaryDisplay().id(); + const int64_t first_display_id = 210000001; + const int64_t second_display_id = 220000002; + display::ManagedDisplayInfo first_display_info = + display::CreateDisplayInfo(first_display_id, gfx::Rect(1, 1, 500, 500)); + display::ManagedDisplayInfo second_display_info = + display::CreateDisplayInfo(second_display_id, gfx::Rect(2, 2, 500, 500)); + std::vector<display::ManagedDisplayInfo> display_info_list; + display_info_list.emplace_back(first_display_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); + ash::Shell::Get()->window_tree_host_manager()->SetPrimaryDisplayId( + first_display_id); + EXPECT_FALSE(display_manager()->IsInUnifiedMode()); + EXPECT_FALSE(display_manager()->IsInMirrorMode()); + display::DisplayIdList list = - display::test::CreateDisplayIdList2(id1, id1 + 1); + display::test::CreateDisplayIdList2(first_display_id, second_display_id); StoreDisplayBoolPropertyForList(list, "default_unified", true); StoreDisplayPropertyForList( list, "primary-id", - base::MakeUnique<base::Value>(base::Int64ToString(id1))); + base::MakeUnique<base::Value>(base::Int64ToString(first_display_id))); LoadDisplayPreferences(false); // Should not restore to unified unless unified desktop is enabled. - UpdateDisplay("100x100,200x200"); + display_info_list.emplace_back(second_display_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_FALSE(display_manager()->IsInUnifiedMode()); // Restored to unified. display_manager()->SetUnifiedDesktopEnabled(true); StoreDisplayBoolPropertyForList(list, "default_unified", true); LoadDisplayPreferences(false); - UpdateDisplay("100x100,200x200"); + display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_TRUE(display_manager()->IsInUnifiedMode()); + // Remove the second display. + display_info_list.erase(display_info_list.end() - 1); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_FALSE(display_manager()->IsInUnifiedMode()); + // Restored to mirror, then unified. - StoreDisplayBoolPropertyForList(list, "mirrored", true); + std::set<int64_t> external_display_mirror_info; + external_display_mirror_info.emplace( + display::GetDisplayIdWithoutOutputIndex(second_display_id)); + StoreExternalDisplayMirrorInfo(external_display_mirror_info); StoreDisplayBoolPropertyForList(list, "default_unified", true); LoadDisplayPreferences(false); - UpdateDisplay("100x100,200x200"); + display_info_list.emplace_back(second_display_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_TRUE(display_manager()->IsInMirrorMode()); display_manager()->SetMirrorMode(false); EXPECT_TRUE(display_manager()->IsInUnifiedMode()); + // Remove the second display. + display_info_list.erase(display_info_list.end() - 1); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_FALSE(display_manager()->IsInUnifiedMode()); + // Sanity check. Restore to extended. + external_display_mirror_info.clear(); + StoreExternalDisplayMirrorInfo(external_display_mirror_info); StoreDisplayBoolPropertyForList(list, "default_unified", false); - StoreDisplayBoolPropertyForList(list, "mirrored", false); LoadDisplayPreferences(false); - UpdateDisplay("100x100,200x200"); + display_info_list.emplace_back(second_display_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_FALSE(display_manager()->IsInMirrorMode()); EXPECT_FALSE(display_manager()->IsInUnifiedMode()); } @@ -1253,4 +1306,114 @@ data_2); } +class MultiMirroringDisplayPreferencesTest : public DisplayPreferencesTest { + public: + MultiMirroringDisplayPreferencesTest() = default; + ~MultiMirroringDisplayPreferencesTest() override = default; + + void SetUp() override { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + ::switches::kEnableMultiMirroring); + DisplayPreferencesTest::SetUp(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(MultiMirroringDisplayPreferencesTest); +}; + +TEST_F(MultiMirroringDisplayPreferencesTest, ExternalDisplayMirrorInfo) { + LoggedInAsUser(); + + const int64_t internal_display_id = + display::test::DisplayManagerTestApi(display_manager()) + .SetFirstDisplayAsInternalDisplay(); + constexpr int64_t first_display_id = 210000001; + constexpr int64_t second_display_id = 220000002; + const int64_t first_display_masked_id = + display::GetDisplayIdWithoutOutputIndex(first_display_id); + const int64_t second_display_masked_id = + display::GetDisplayIdWithoutOutputIndex(second_display_id); + display::ManagedDisplayInfo first_display_info = + display::CreateDisplayInfo(first_display_id, gfx::Rect(1, 1, 500, 500)); + display::ManagedDisplayInfo second_display_info = + display::CreateDisplayInfo(second_display_id, gfx::Rect(2, 2, 500, 500)); + std::vector<display::ManagedDisplayInfo> display_info_list; + + // There's no external display now. + display_info_list.push_back(display::CreateDisplayInfo( + internal_display_id, gfx::Rect(0, 0, 100, 100))); + display_manager()->OnNativeDisplaysChanged(display_info_list); + + // Add first display id to the external display mirror info. + std::set<int64_t> external_display_mirror_info; + external_display_mirror_info.emplace(first_display_masked_id); + StoreExternalDisplayMirrorInfo(external_display_mirror_info); + LoadDisplayPreferences(true); + const base::ListValue* pref_external_display_mirror_info = + local_state()->GetList(prefs::kExternalDisplayMirrorInfo); + EXPECT_EQ(1U, pref_external_display_mirror_info->GetSize()); + EXPECT_EQ(base::Int64ToString(first_display_masked_id), + pref_external_display_mirror_info->GetList()[0].GetString()); + + // Add first display, mirror mode restores and the external display mirror + // info does not change. + display_info_list.emplace_back(first_display_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_TRUE(display_manager()->IsInMirrorMode()); + pref_external_display_mirror_info = + local_state()->GetList(prefs::kExternalDisplayMirrorInfo); + EXPECT_EQ(1U, pref_external_display_mirror_info->GetSize()); + EXPECT_EQ(base::Int64ToString(first_display_masked_id), + pref_external_display_mirror_info->GetList()[0].GetString()); + + // Add second display, mirror mode persists and the second display id is added + // to the external display mirror info. + display_info_list.emplace_back(second_display_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_TRUE(display_manager()->IsInMirrorMode()); + pref_external_display_mirror_info = + local_state()->GetList(prefs::kExternalDisplayMirrorInfo); + EXPECT_EQ(2U, pref_external_display_mirror_info->GetSize()); + EXPECT_EQ(base::Int64ToString(first_display_masked_id), + pref_external_display_mirror_info->GetList()[0].GetString()); + EXPECT_EQ(base::Int64ToString(second_display_masked_id), + pref_external_display_mirror_info->GetList()[1].GetString()); + + // Disconnect all external displays. + display_info_list.erase(display_info_list.begin() + 1, + display_info_list.end()); + display_manager()->OnNativeDisplaysChanged(display_info_list); + + // Clear external display mirror info and only add second display id to it. + external_display_mirror_info.clear(); + external_display_mirror_info.emplace(second_display_masked_id); + StoreExternalDisplayMirrorInfo(external_display_mirror_info); + LoadDisplayPreferences(false); + pref_external_display_mirror_info = + local_state()->GetList(prefs::kExternalDisplayMirrorInfo); + EXPECT_EQ(1U, pref_external_display_mirror_info->GetSize()); + EXPECT_EQ(base::Int64ToString(second_display_masked_id), + pref_external_display_mirror_info->GetList()[0].GetString()); + + // Add first display, mirror mode is off and the external display mirror info + // does not change. + display_info_list.emplace_back(first_display_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_FALSE(display_manager()->IsInMirrorMode()); + pref_external_display_mirror_info = + local_state()->GetList(prefs::kExternalDisplayMirrorInfo); + EXPECT_EQ(1U, pref_external_display_mirror_info->GetSize()); + EXPECT_EQ(base::Int64ToString(second_display_masked_id), + pref_external_display_mirror_info->GetList()[0].GetString()); + + // Add second display, mirror mode remains off and the second display id is + // removed from the external display mirror info. + display_info_list.emplace_back(second_display_info); + display_manager()->OnNativeDisplaysChanged(display_info_list); + EXPECT_FALSE(display_manager()->IsInMirrorMode()); + pref_external_display_mirror_info = + local_state()->GetList(prefs::kExternalDisplayMirrorInfo); + EXPECT_EQ(0U, pref_external_display_mirror_info->GetSize()); +} + } // namespace chromeos
diff --git a/chrome/browser/chromeos/enrollment_dialog_view.cc b/chrome/browser/chromeos/enrollment_dialog_view.cc index a2192b3..bcf47eb 100644 --- a/chrome/browser/chromeos/enrollment_dialog_view.cc +++ b/chrome/browser/chromeos/enrollment_dialog_view.cc
@@ -165,7 +165,8 @@ label->SetMultiLine(true); label->SetAllowCharacterBreak(true); - views::GridLayout* grid_layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* grid_layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); views::ColumnSet* columns = grid_layout->AddColumnSet(0); columns->AddColumn(views::GridLayout::FILL, // Horizontal resize.
diff --git a/chrome/browser/chromeos/input_method/input_method_engine.cc b/chrome/browser/chromeos/input_method/input_method_engine.cc index 0eb272f..463f6be 100644 --- a/chrome/browser/chromeos/input_method/input_method_engine.cc +++ b/chrome/browser/chromeos/input_method/input_method_engine.cc
@@ -31,8 +31,8 @@ #include "ui/events/event_utils.h" #include "ui/events/keycodes/dom/dom_code.h" #include "ui/events/keycodes/dom/keycode_converter.h" +#include "ui/keyboard/content/keyboard_content_util.h" #include "ui/keyboard/keyboard_controller.h" -#include "ui/keyboard/keyboard_util.h" using input_method::InputMethodEngineBase;
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc index 7c5905a..5861272 100644 --- a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc +++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
@@ -49,8 +49,8 @@ #include "ui/base/ime/ime_bridge.h" #include "ui/chromeos/ime/input_method_menu_item.h" #include "ui/chromeos/ime/input_method_menu_manager.h" +#include "ui/keyboard/content/keyboard_content_util.h" #include "ui/keyboard/keyboard_controller.h" -#include "ui/keyboard/keyboard_util.h" namespace chromeos { namespace input_method {
diff --git a/chrome/browser/chromeos/login/ui/simple_web_view_dialog.cc b/chrome/browser/chromeos/login/ui/simple_web_view_dialog.cc index 20bc115..77d3e90d 100644 --- a/chrome/browser/chromeos/login/ui/simple_web_view_dialog.cc +++ b/chrome/browser/chromeos/login/ui/simple_web_view_dialog.cc
@@ -12,7 +12,7 @@ #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/chromeos/login/helper.h" #include "chrome/browser/chromeos/login/ui/captive_portal_window_proxy.h" -#include "chrome/browser/command_updater.h" +#include "chrome/browser/command_updater_impl.h" #include "chrome/browser/password_manager/chrome_password_manager_client.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ssl/security_state_tab_helper.h" @@ -67,7 +67,7 @@ views::View* forward, views::View* reload, views::View* location_bar) { - GridLayout* layout = GridLayout::CreateAndInstall(this); + GridLayout* layout = SetLayoutManager(std::make_unique<GridLayout>(this)); const int related_horizontal_spacing = ChromeLayoutProvider::Get()->GetDistanceMetric( @@ -127,7 +127,7 @@ SimpleWebViewDialog::SimpleWebViewDialog(Profile* profile) : profile_(profile), bubble_model_delegate_(new StubBubbleModelDelegate) { - command_updater_.reset(new CommandUpdater(this)); + command_updater_.reset(new CommandUpdaterImpl(this)); command_updater_->UpdateCommandEnabled(IDC_BACK, true); command_updater_->UpdateCommandEnabled(IDC_FORWARD, true); command_updater_->UpdateCommandEnabled(IDC_STOP, true); @@ -204,7 +204,7 @@ toolbar_row->Init(back_, forward_, reload_, location_bar_); // Layout. - GridLayout* layout = GridLayout::CreateAndInstall(this); + GridLayout* layout = SetLayoutManager(std::make_unique<GridLayout>(this)); views::ColumnSet* column_set = layout->AddColumnSet(0); column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
diff --git a/chrome/browser/chromeos/login/ui/simple_web_view_dialog.h b/chrome/browser/chromeos/login/ui/simple_web_view_dialog.h index 1b5af76..5177c51 100644 --- a/chrome/browser/chromeos/login/ui/simple_web_view_dialog.h +++ b/chrome/browser/chromeos/login/ui/simple_web_view_dialog.h
@@ -18,7 +18,7 @@ #include "ui/views/widget/widget_delegate.h" #include "url/gurl.h" -class CommandUpdater; +class CommandUpdaterImpl; class Profile; class ReloadButton; class ToolbarModel; @@ -94,7 +94,7 @@ Profile* profile_; std::unique_ptr<ToolbarModel> toolbar_model_; - std::unique_ptr<CommandUpdater> command_updater_; + std::unique_ptr<CommandUpdaterImpl> command_updater_; // Controls views::ImageButton* back_ = nullptr;
diff --git a/chrome/browser/chromeos/options/vpn_config_view.cc b/chrome/browser/chromeos/options/vpn_config_view.cc index 14a267dd..bcddaa2 100644 --- a/chrome/browser/chromeos/options/vpn_config_view.cc +++ b/chrome/browser/chromeos/options/vpn_config_view.cc
@@ -506,7 +506,8 @@ DCHECK(vpn && vpn->type() == shill::kTypeVPN); } - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); // Observer any changes to the certificate list. CertLibrary::Get()->AddObserver(this);
diff --git a/chrome/browser/chromeos/options/wifi_config_view.cc b/chrome/browser/chromeos/options/wifi_config_view.cc index 5ea38149..cb6b0a3 100644 --- a/chrome/browser/chromeos/options/wifi_config_view.cc +++ b/chrome/browser/chromeos/options/wifi_config_view.cc
@@ -943,7 +943,8 @@ ParseUIProperty(&passphrase_ui_data_, network, ::onc::wifi::kPassphrase); } - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); const int column_view_set_id = 0; views::ColumnSet* column_set = layout->AddColumnSet(column_view_set_id);
diff --git a/chrome/browser/chromeos/options/wimax_config_view.cc b/chrome/browser/chromeos/options/wimax_config_view.cc index d28c71b..fc498ec 100644 --- a/chrome/browser/chromeos/options/wimax_config_view.cc +++ b/chrome/browser/chromeos/options/wimax_config_view.cc
@@ -212,7 +212,8 @@ WifiConfigView::ParseUIProperty( &passphrase_ui_data_, wimax, ::onc::wifi::kPassphrase); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); const int column_view_set_id = 0; views::ColumnSet* column_set = layout->AddColumnSet(column_view_set_id);
diff --git a/chrome/browser/chromeos/policy/active_directory_policy_manager_unittest.cc b/chrome/browser/chromeos/policy/active_directory_policy_manager_unittest.cc index 1d9aacb0..9374d1e3 100644 --- a/chrome/browser/chromeos/policy/active_directory_policy_manager_unittest.cc +++ b/chrome/browser/chromeos/policy/active_directory_policy_manager_unittest.cc
@@ -40,7 +40,7 @@ NOTIMPLEMENTED(); } - void GetUserStatus(const std::string& object_guid, + void GetUserStatus(const authpolicy::GetUserStatusRequest& request, GetUserStatusCallback callback) override { NOTIMPLEMENTED(); }
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc index 440f833..28ac1cf69 100644 --- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc +++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc
@@ -90,7 +90,9 @@ const chromeos::attestation::AttestationFlow::CertificateCallback& callback) { base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(callback, true, "fake_cert")); + FROM_HERE, + base::BindOnce(callback, chromeos::attestation::ATTESTATION_SUCCESS, + "fake_cert")); } class TestingDeviceCloudPolicyManagerChromeOS
diff --git a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc index f271848..c30fc81 100644 --- a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc +++ b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc
@@ -391,9 +391,9 @@ } void EnrollmentHandlerChromeOS::HandleRegistrationCertificateResult( - bool success, + chromeos::attestation::AttestationStatus status, const std::string& pem_certificate_chain) { - if (success) + if (status == chromeos::attestation::ATTESTATION_SUCCESS) client_->RegisterWithCertificate( em::DeviceRegisterRequest::DEVICE, EnrollmentModeToRegistrationFlavor(enrollment_config_.mode),
diff --git a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h index 0e6fd0e..2a12cd9 100644 --- a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h +++ b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h
@@ -17,6 +17,7 @@ #include "chrome/browser/chromeos/policy/device_cloud_policy_validator.h" #include "chrome/browser/chromeos/policy/enrollment_config.h" #include "chrome/browser/chromeos/settings/install_attributes.h" +#include "chromeos/attestation/attestation_constants.h" #include "chromeos/dbus/auth_policy_client.h" #include "components/policy/core/common/cloud/cloud_policy_client.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" @@ -145,7 +146,7 @@ // Handles the response to a request for a registration certificate. void HandleRegistrationCertificateResult( - bool success, + chromeos::attestation::AttestationStatus status, const std::string& pem_certificate_chain); // Starts registration if the store is initialized.
diff --git a/chrome/browser/chromeos/power/renderer_freezer_unittest.cc b/chrome/browser/chromeos/power/renderer_freezer_unittest.cc index a8ba431..0751b71 100644 --- a/chrome/browser/chromeos/power/renderer_freezer_unittest.cc +++ b/chrome/browser/chromeos/power/renderer_freezer_unittest.cc
@@ -260,7 +260,7 @@ extensions::ProcessManager::Get(profile_)->GetSiteInstanceForURL( extensions::BackgroundInfo::GetBackgroundURL(extension))); std::unique_ptr<content::RenderProcessHost> rph( - rph_factory->CreateRenderProcessHost(profile_)); + rph_factory->CreateRenderProcessHost(profile_, site_instance.get())); // Fake that the RenderProcessHost is hosting the gcm app. extensions::ProcessMap::Get(profile_) @@ -297,7 +297,7 @@ scoped_refptr<content::SiteInstance> site_instance( content::SiteInstance::Create(profile_)); std::unique_ptr<content::RenderProcessHost> rph( - rph_factory->CreateRenderProcessHost(profile_)); + rph_factory->CreateRenderProcessHost(profile_, site_instance.get())); // Send the notification that the RenderProcessHost has been created. content::NotificationService::current()->Notify(
diff --git a/chrome/browser/chromeos/profiles/profile_helper.h b/chrome/browser/chromeos/profiles/profile_helper.h index ee07d930..39e4652 100644 --- a/chrome/browser/chromeos/profiles/profile_helper.h +++ b/chrome/browser/chromeos/profiles/profile_helper.h
@@ -19,6 +19,7 @@ #include "content/public/browser/browsing_data_remover.h" class ArcAppTest; +class IndependentOTRProfileManagerTest; class SessionControllerClientTest; class Profile; @@ -191,6 +192,7 @@ friend class ::ArcAppTest; friend class ::SessionControllerClientTest; friend class ::test::BrowserFinderChromeOSTest; + friend class ::IndependentOTRProfileManagerTest; // Called when signin profile is cleared. void OnSigninProfileCleared();
diff --git a/chrome/browser/chromeos/settings/device_settings_provider.cc b/chrome/browser/chromeos/settings/device_settings_provider.cc index 6edcc52..ee296895 100644 --- a/chrome/browser/chromeos/settings/device_settings_provider.cc +++ b/chrome/browser/chromeos/settings/device_settings_provider.cc
@@ -66,7 +66,6 @@ kDeviceAttestationEnabled, kDeviceDisabled, kDeviceDisabledMessage, - kDeviceEnrollmentIdNeeded, kDeviceHostnameTemplate, kDeviceLoginScreenAppInstallList, kDeviceLoginScreenInputMethods, @@ -608,15 +607,6 @@ } } - if (policy.has_forced_reenrollment()) { - const em::ForcedReenrollmentProto& container(policy.forced_reenrollment()); - if (container.has_enrollment_id_needed()) { - new_values_cache->SetValue( - kDeviceEnrollmentIdNeeded, - base::MakeUnique<base::Value>(container.enrollment_id_needed())); - } - } - if (policy.has_unaffiliated_arc_allowed()) { const em::UnaffiliatedArcAllowedProto& container( policy.unaffiliated_arc_allowed());
diff --git a/chrome/browser/chromeos/ui/request_pin_view.cc b/chrome/browser/chromeos/ui/request_pin_view.cc index 033c3639b..1106c0cd 100644 --- a/chrome/browser/chromeos/ui/request_pin_view.cc +++ b/chrome/browser/chromeos/ui/request_pin_view.cc
@@ -164,7 +164,8 @@ set_margins(ChromeLayoutProvider::Get()->GetDialogInsetsForContentType( views::TEXT, views::TEXT)); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); int column_view_set_id = 0; views::ColumnSet* column_set = layout->AddColumnSet(column_view_set_id);
diff --git a/chrome/browser/command_updater.cc b/chrome/browser/command_updater.cc deleted file mode 100644 index 5321e01..0000000 --- a/chrome/browser/command_updater.cc +++ /dev/null
@@ -1,89 +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 "chrome/browser/command_updater.h" - -#include <algorithm> - -#include "base/logging.h" -#include "base/memory/ptr_util.h" -#include "base/observer_list.h" -#include "chrome/browser/command_observer.h" -#include "chrome/browser/command_updater_delegate.h" - -class CommandUpdater::Command { - public: - bool enabled; - base::ObserverList<CommandObserver> observers; - - Command() : enabled(true) {} -}; - -CommandUpdater::CommandUpdater(CommandUpdaterDelegate* delegate) - : delegate_(delegate) { -} - -CommandUpdater::~CommandUpdater() { -} - -bool CommandUpdater::SupportsCommand(int id) const { - return commands_.find(id) != commands_.end(); -} - -bool CommandUpdater::IsCommandEnabled(int id) const { - auto command = commands_.find(id); - if (command == commands_.end()) - return false; - return command->second->enabled; -} - -bool CommandUpdater::ExecuteCommand(int id) { - return ExecuteCommandWithDisposition(id, WindowOpenDisposition::CURRENT_TAB); -} - -bool CommandUpdater::ExecuteCommandWithDisposition( - int id, - WindowOpenDisposition disposition) { - if (SupportsCommand(id) && IsCommandEnabled(id)) { - delegate_->ExecuteCommandWithDisposition(id, disposition); - return true; - } - return false; -} - -void CommandUpdater::AddCommandObserver(int id, CommandObserver* observer) { - GetCommand(id, true)->observers.AddObserver(observer); -} - -void CommandUpdater::RemoveCommandObserver(int id, CommandObserver* observer) { - GetCommand(id, false)->observers.RemoveObserver(observer); -} - -void CommandUpdater::RemoveCommandObserver(CommandObserver* observer) { - for (const auto& command_pair : commands_) { - Command* command = command_pair.second.get(); - if (command) - command->observers.RemoveObserver(observer); - } -} - -void CommandUpdater::UpdateCommandEnabled(int id, bool enabled) { - Command* command = GetCommand(id, true); - if (command->enabled == enabled) - return; // Nothing to do. - command->enabled = enabled; - for (auto& observer : command->observers) - observer.EnabledStateChangedForCommand(id, enabled); -} - -CommandUpdater::Command* CommandUpdater::GetCommand(int id, bool create) { - bool supported = SupportsCommand(id); - if (supported) - return commands_[id].get(); - - DCHECK(create); - std::unique_ptr<Command>& entry = commands_[id]; - entry = base::MakeUnique<Command>(); - return entry.get(); -}
diff --git a/chrome/browser/command_updater.h b/chrome/browser/command_updater.h index 035d250..77c2655b 100644 --- a/chrome/browser/command_updater.h +++ b/chrome/browser/command_updater.h
@@ -5,81 +5,64 @@ #ifndef CHROME_BROWSER_COMMAND_UPDATER_H_ #define CHROME_BROWSER_COMMAND_UPDATER_H_ -#include <memory> -#include <unordered_map> - -#include "base/macros.h" #include "ui/base/window_open_disposition.h" class CommandObserver; -class CommandUpdaterDelegate; //////////////////////////////////////////////////////////////////////////////// // -// CommandUpdater class +// CommandUpdater interface // -// This object manages the enabled state of a set of commands. Observers -// register to listen to changes in this state so they can update their -// presentation. +// This is the public API to manage the enabled state of a set of commands. +// Observers register to listen to changes in this state so they can update +// their presentation. +// +// The actual implementation of this is in CommandUpdaterImpl, this interface +// exists purely so that classes using the actual CommandUpdaterImpl can +// expose it through a safe public interface (as opposed to directly exposing +// the private implementation details). // class CommandUpdater { public: - // Create a CommandUpdater with |delegate| to handle the execution of specific - // commands. - explicit CommandUpdater(CommandUpdaterDelegate* delegate); - ~CommandUpdater(); + virtual ~CommandUpdater() {} // Returns true if the specified command ID is supported. - bool SupportsCommand(int id) const; + virtual bool SupportsCommand(int id) const = 0; // Returns true if the specified command ID is enabled. The command ID must be // supported by this updater. - bool IsCommandEnabled(int id) const; + virtual bool IsCommandEnabled(int id) const = 0; // Performs the action associated with this command ID using CURRENT_TAB // disposition. // Returns true if the command was executed (i.e. it is supported and is // enabled). - bool ExecuteCommand(int id); + virtual bool ExecuteCommand(int id) = 0; // Performs the action associated with this command ID using the given // disposition. // Returns true if the command was executed (i.e. it is supported and is // enabled). - bool ExecuteCommandWithDisposition(int id, WindowOpenDisposition disposition); + virtual bool ExecuteCommandWithDisposition( + int id, WindowOpenDisposition disposition) = 0; // Adds an observer to the state of a particular command. If the command does // not exist, it is created, initialized to false. - void AddCommandObserver(int id, CommandObserver* observer); + virtual void AddCommandObserver(int id, CommandObserver* observer) = 0; // Removes an observer to the state of a particular command. - void RemoveCommandObserver(int id, CommandObserver* observer); + virtual void RemoveCommandObserver(int id, CommandObserver* observer) = 0; // Removes |observer| for all commands on which it's registered. - void RemoveCommandObserver(CommandObserver* observer); + virtual void RemoveCommandObserver(CommandObserver* observer) = 0; // Notify all observers of a particular command that the command has been // enabled or disabled. If the command does not exist, it is created and // initialized to |state|. This function is very lightweight if the command // state has not changed. - void UpdateCommandEnabled(int id, bool state); - - private: - // A piece of data about a command - whether or not it is enabled, and a list - // of objects that observe the enabled state of this command. - class Command; - - // Get a Command node for a given command ID, creating an entry if it doesn't - // exist if desired. - Command* GetCommand(int id, bool create); - - // The delegate is responsible for executing commands. - CommandUpdaterDelegate* delegate_; - - // This is a map of command IDs to states and observer lists - std::unordered_map<int, std::unique_ptr<Command>> commands_; - - DISALLOW_COPY_AND_ASSIGN(CommandUpdater); + // Returns true if the update succeeded (it's possible that the browser is in + // "locked-down" state where we prevent changes to the command state). + virtual bool UpdateCommandEnabled(int id, bool state) = 0; }; #endif // CHROME_BROWSER_COMMAND_UPDATER_H_
diff --git a/chrome/browser/command_updater_impl.cc b/chrome/browser/command_updater_impl.cc new file mode 100644 index 0000000..2109874 --- /dev/null +++ b/chrome/browser/command_updater_impl.cc
@@ -0,0 +1,104 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/command_updater_impl.h" + +#include <algorithm> + +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "base/observer_list.h" +#include "chrome/browser/command_observer.h" +#include "chrome/browser/command_updater_delegate.h" + +class CommandUpdaterImpl::Command { + public: + bool enabled; + base::ObserverList<CommandObserver> observers; + + Command() : enabled(true) {} +}; + +CommandUpdaterImpl::CommandUpdaterImpl(CommandUpdaterDelegate* delegate) + : delegate_(delegate) { +} + +CommandUpdaterImpl::~CommandUpdaterImpl() { +} + +bool CommandUpdaterImpl::SupportsCommand(int id) const { + return commands_.find(id) != commands_.end(); +} + +bool CommandUpdaterImpl::IsCommandEnabled(int id) const { + auto command = commands_.find(id); + if (command == commands_.end()) + return false; + return command->second->enabled; +} + +bool CommandUpdaterImpl::ExecuteCommand(int id) { + return ExecuteCommandWithDisposition(id, WindowOpenDisposition::CURRENT_TAB); +} + +bool CommandUpdaterImpl::ExecuteCommandWithDisposition( + int id, + WindowOpenDisposition disposition) { + if (SupportsCommand(id) && IsCommandEnabled(id)) { + delegate_->ExecuteCommandWithDisposition(id, disposition); + return true; + } + return false; +} + +void CommandUpdaterImpl::AddCommandObserver(int id, CommandObserver* observer) { + GetCommand(id, true)->observers.AddObserver(observer); +} + +void CommandUpdaterImpl::RemoveCommandObserver( + int id, CommandObserver* observer) { + GetCommand(id, false)->observers.RemoveObserver(observer); +} + +void CommandUpdaterImpl::RemoveCommandObserver(CommandObserver* observer) { + for (const auto& command_pair : commands_) { + Command* command = command_pair.second.get(); + if (command) + command->observers.RemoveObserver(observer); + } +} + +bool CommandUpdaterImpl::UpdateCommandEnabled(int id, bool enabled) { + Command* command = GetCommand(id, true); + if (command->enabled == enabled) + return true; // Nothing to do. + command->enabled = enabled; + for (auto& observer : command->observers) + observer.EnabledStateChangedForCommand(id, enabled); + return true; +} + +void CommandUpdaterImpl::DisableAllCommands() { + for (const auto& command_pair : commands_) + UpdateCommandEnabled(command_pair.first, false); +} + +std::vector<int> CommandUpdaterImpl::GetAllIds() { + std::vector<int> result; + for (const auto& command_pair : commands_) + result.push_back(command_pair.first); + return result; +} + +CommandUpdaterImpl::Command* +CommandUpdaterImpl::GetCommand(int id, bool create) { + bool supported = SupportsCommand(id); + if (supported) + return commands_[id].get(); + + DCHECK(create); + std::unique_ptr<Command>& entry = commands_[id]; + entry = base::MakeUnique<Command>(); + return entry.get(); +}
diff --git a/chrome/browser/command_updater_impl.h b/chrome/browser/command_updater_impl.h new file mode 100644 index 0000000..59ff772 --- /dev/null +++ b/chrome/browser/command_updater_impl.h
@@ -0,0 +1,66 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_COMMAND_UPDATER_IMPL_H_ +#define CHROME_BROWSER_COMMAND_UPDATER_IMPL_H_ + +#include <memory> +#include <unordered_map> +#include <vector> + +#include "chrome/browser/command_updater.h" +#include "base/macros.h" +#include "ui/base/window_open_disposition.h" + +class CommandObserver; +class CommandUpdaterDelegate; + +//////////////////////////////////////////////////////////////////////////////// +// +// CommandUpdaterImpl class +// +// This object manages the enabled state of a set of commands. Observers +// register to listen to changes in this state so they can update their +// presentation. +// +class CommandUpdaterImpl : public CommandUpdater { + public: + // Create a CommandUpdaterImpl with |delegate| to handle the execution of + // specific commands. + explicit CommandUpdaterImpl(CommandUpdaterDelegate* delegate); + ~CommandUpdaterImpl() override; + + // Overriden from CommandUpdater: + bool SupportsCommand(int id) const override; + bool IsCommandEnabled(int id) const override; + bool ExecuteCommand(int id) override; + bool ExecuteCommandWithDisposition( + int id, WindowOpenDisposition disposition) override; + void AddCommandObserver(int id, CommandObserver* observer) override; + void RemoveCommandObserver(int id, CommandObserver* observer) override; + void RemoveCommandObserver(CommandObserver* observer) override; + bool UpdateCommandEnabled(int id, bool state) override; + + void DisableAllCommands(); + std::vector<int> GetAllIds(); + + private: + // A piece of data about a command - whether or not it is enabled, and a list + // of objects that observe the enabled state of this command. + class Command; + + // Get a Command node for a given command ID, creating an entry if it doesn't + // exist if desired. + Command* GetCommand(int id, bool create); + + // The delegate is responsible for executing commands. + CommandUpdaterDelegate* delegate_; + + // This is a map of command IDs to states and observer lists + std::unordered_map<int, std::unique_ptr<Command>> commands_; + + DISALLOW_COPY_AND_ASSIGN(CommandUpdaterImpl); +}; + +#endif // CHROME_BROWSER_COMMAND_UPDATER_IMPL_H_
diff --git a/chrome/browser/command_updater_unittest.cc b/chrome/browser/command_updater_impl_unittest.cc similarity index 90% rename from chrome/browser/command_updater_unittest.cc rename to chrome/browser/command_updater_impl_unittest.cc index 9e94bf4..a08c482 100644 --- a/chrome/browser/command_updater_unittest.cc +++ b/chrome/browser/command_updater_impl_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/command_updater.h" +#include "chrome/browser/command_updater_impl.h" #include "base/compiler_specific.h" #include "chrome/browser/command_observer.h" @@ -30,9 +30,9 @@ bool enabled_; }; -TEST(CommandUpdaterTest, TestBasicAPI) { +TEST(CommandUpdaterImplTest, TestBasicAPI) { FakeCommandUpdaterDelegate delegate; - CommandUpdater command_updater(&delegate); + CommandUpdaterImpl command_updater(&delegate); // Unsupported command EXPECT_FALSE(command_updater.SupportsCommand(0)); @@ -56,9 +56,9 @@ command_updater.ExecuteCommand(2); } -TEST(CommandUpdaterTest, TestObservers) { +TEST(CommandUpdaterImplTest, TestObservers) { FakeCommandUpdaterDelegate delegate; - CommandUpdater command_updater(&delegate); + CommandUpdaterImpl command_updater(&delegate); // Create an observer for the command 2 and add it to the controller, then // update the command. @@ -75,9 +75,9 @@ EXPECT_FALSE(observer.enabled()); } -TEST(CommandUpdaterTest, TestObserverRemovingAllCommands) { +TEST(CommandUpdaterImplTest, TestObserverRemovingAllCommands) { FakeCommandUpdaterDelegate delegate; - CommandUpdater command_updater(&delegate); + CommandUpdaterImpl command_updater(&delegate); // Create two observers for the commands 1-3 as true, remove one using the // single remove command, then set the command to false. Ensure that the
diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc index fe68ae57..874f7735 100644 --- a/chrome/browser/devtools/devtools_ui_bindings.cc +++ b/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -636,7 +636,7 @@ void DevToolsUIBindings::DispatchProtocolMessage( content::DevToolsAgentHost* agent_host, const std::string& message) { DCHECK(agent_host == agent_host_.get()); - if (!frontend_host_) + if (!frontend_host_ || reloading_) return; if (message.length() < kMaxMessageChunkSize) { @@ -1070,7 +1070,7 @@ void DevToolsUIBindings::DispatchProtocolMessageFromDevToolsFrontend( const std::string& message) { - if (agent_host_.get()) + if (agent_host_.get() && !reloading_) agent_host_->DispatchProtocolMessage(this, message); } @@ -1322,8 +1322,6 @@ void DevToolsUIBindings::Reload() { reloading_ = true; - if (agent_host_) - agent_host_->DetachClient(this); web_contents_->GetController().Reload(content::ReloadType::NORMAL, false); } @@ -1406,8 +1404,10 @@ if (!reloading_) return; reloading_ = false; - if (agent_host_.get()) + if (agent_host_.get()) { + agent_host_->DetachClient(this); InnerAttach(); + } } void DevToolsUIBindings::DocumentOnLoadCompletedInMainFrame() {
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn index 04f56f2..bd83907 100644 --- a/chrome/browser/extensions/BUILD.gn +++ b/chrome/browser/extensions/BUILD.gn
@@ -555,8 +555,6 @@ "extension_disabled_ui.h", "extension_error_controller.cc", "extension_error_controller.h", - "extension_error_reporter.cc", - "extension_error_reporter.h", "extension_error_ui.cc", "extension_error_ui.h", "extension_error_ui_default.cc", @@ -669,6 +667,8 @@ "installed_loader.h", "launch_util.cc", "launch_util.h", + "load_error_reporter.cc", + "load_error_reporter.h", "menu_manager.cc", "menu_manager.h", "menu_manager_factory.cc",
diff --git a/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc b/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc index 32762820..a3502dc 100644 --- a/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc +++ b/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc
@@ -35,6 +35,7 @@ #include "chrome/browser/ui/ash/login_screen_client.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/session_manager_client.h" +#include "chromeos/printing/printer_configuration.h" #include "components/user_manager/user_manager.h" #include "ui/message_center/message_center.h" #include "ui/message_center/notification.h" @@ -412,6 +413,51 @@ return RespondNow(OneArgument(std::move(values))); } +#if defined(OS_CHROMEOS) +// static +std::string AutotestPrivateGetPrinterListFunction::GetPrinterType( + chromeos::CupsPrintersManager::PrinterClass type) { + switch (type) { + case chromeos::CupsPrintersManager::PrinterClass::kConfigured: + return "configured"; + case chromeos::CupsPrintersManager::PrinterClass::kEnterprise: + return "enterprise"; + case chromeos::CupsPrintersManager::PrinterClass::kAutomatic: + return "automatic"; + case chromeos::CupsPrintersManager::PrinterClass::kDiscovered: + return "discovered"; + default: + return "unknown"; + } +} +#endif + +ExtensionFunction::ResponseAction AutotestPrivateGetPrinterListFunction::Run() { + DVLOG(1) << "AutotestPrivateGetPrinterListFunction"; + auto values = std::make_unique<base::ListValue>(); +#if defined(OS_CHROMEOS) + Profile* profile = ProfileManager::GetActiveUserProfile(); + std::unique_ptr<chromeos::CupsPrintersManager> printers_manager = + chromeos::CupsPrintersManager::Create(profile); + std::vector<chromeos::CupsPrintersManager::PrinterClass> printer_type = { + chromeos::CupsPrintersManager::PrinterClass::kConfigured, + chromeos::CupsPrintersManager::PrinterClass::kEnterprise, + chromeos::CupsPrintersManager::PrinterClass::kAutomatic}; + for (const auto& type : printer_type) { + std::vector<chromeos::Printer> printer_list = + printers_manager->GetPrinters(type); + for (const auto& printer : printer_list) { + auto result = std::make_unique<base::DictionaryValue>(); + result->SetString("printerName", printer.display_name()); + result->SetString("printerId", printer.id()); + result->SetString("printerType", GetPrinterType(type)); + values->Append(std::move(result)); + } + } +#endif + return RespondNow(OneArgument(std::move(values))); +} + ExtensionFunction::ResponseAction AutotestPrivateGetPlayStoreStateFunction::Run() { DVLOG(1) << "AutotestPrivateGetPlayStoreStateFunction";
diff --git a/chrome/browser/extensions/api/autotest_private/autotest_private_api.h b/chrome/browser/extensions/api/autotest_private/autotest_private_api.h index 19fe8173..7f55a38 100644 --- a/chrome/browser/extensions/api/autotest_private/autotest_private_api.h +++ b/chrome/browser/extensions/api/autotest_private/autotest_private_api.h
@@ -12,6 +12,10 @@ #include "extensions/browser/browser_context_keyed_api_factory.h" #include "ui/message_center/notification_types.h" +#if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/printing/cups_printers_manager.h" +#endif + namespace extensions { class AutotestPrivateLogoutFunction : public UIThreadExtensionFunction { @@ -209,6 +213,23 @@ ResponseAction Run() override; }; +class AutotestPrivateGetPrinterListFunction : public UIThreadExtensionFunction { + public: + AutotestPrivateGetPrinterListFunction() = default; + DECLARE_EXTENSION_FUNCTION("autotestPrivate.getPrinterList", + AUTOTESTPRIVATE_GETPRINTERLIST) + + private: +#if defined(OS_CHROMEOS) + static std::string GetPrinterType( + chromeos::CupsPrintersManager::PrinterClass type); +#endif + ~AutotestPrivateGetPrinterListFunction() override = default; + ResponseAction Run() override; + + DISALLOW_COPY_AND_ASSIGN(AutotestPrivateGetPrinterListFunction); +}; + // Don't kill the browser when we're in a browser test. void SetAutotestPrivateTest();
diff --git a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc index 336c3c9..bb29bc11 100644 --- a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc +++ b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
@@ -13,8 +13,8 @@ #include "base/test/histogram_tester.h" #include "base/threading/thread_restrictions.h" #include "chrome/browser/extensions/extension_browsertest.h" -#include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/extensions/extension_util.h" +#include "chrome/browser/extensions/load_error_reporter.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/webui_url_constants.h" @@ -173,7 +173,7 @@ content::RunAllTasksUntilIdle(); // Ensure no load errors were reported. - EXPECT_TRUE(ExtensionErrorReporter::GetInstance()->GetErrors()->empty()); + EXPECT_TRUE(LoadErrorReporter::GetInstance()->GetErrors()->empty()); tester.ExpectTotalCount(kIndexRulesTimeHistogram, 1); tester.ExpectTotalCount(kIndexAndPersistRulesTimeHistogram, 1);
diff --git a/chrome/browser/extensions/api/declarative_net_request/rule_indexing_unittest.cc b/chrome/browser/extensions/api/declarative_net_request/rule_indexing_unittest.cc index 6d464d8f..e8b3fff 100644 --- a/chrome/browser/extensions/api/declarative_net_request/rule_indexing_unittest.cc +++ b/chrome/browser/extensions/api/declarative_net_request/rule_indexing_unittest.cc
@@ -14,8 +14,8 @@ #include "base/test/histogram_tester.h" #include "chrome/browser/extensions/api/declarative_net_request/dnr_test_base.h" #include "chrome/browser/extensions/chrome_test_extension_loader.h" -#include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/load_error_reporter.h" #include "extensions/browser/api/declarative_net_request/constants.h" #include "extensions/browser/api/declarative_net_request/parse_info.h" #include "extensions/browser/api/declarative_net_request/test_utils.h" @@ -149,8 +149,8 @@ } } - ExtensionErrorReporter* error_reporter() { - return ExtensionErrorReporter::GetInstance(); + LoadErrorReporter* error_reporter() { + return LoadErrorReporter::GetInstance(); } std::vector<TestRule> rules_list_;
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc index 5366fa0..f190258 100644 --- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc +++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -85,6 +85,7 @@ #include "storage/browser/fileapi/file_system_operation_runner.h" #include "storage/browser/fileapi/isolated_context.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/base/text/bytes_formatting.h" namespace extensions { @@ -659,6 +660,48 @@ : OneArgument(list[0].ToValue())); } +DeveloperPrivateGetExtensionSizeFunction:: + DeveloperPrivateGetExtensionSizeFunction() {} + +DeveloperPrivateGetExtensionSizeFunction:: + ~DeveloperPrivateGetExtensionSizeFunction() {} + +ExtensionFunction::ResponseAction +DeveloperPrivateGetExtensionSizeFunction::Run() { + std::unique_ptr<developer::GetExtensionSize::Params> params( + developer::GetExtensionSize::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params); + + const Extension* extension = GetExtensionById(params->id); + if (!extension) + return RespondNow(Error(kNoSuchExtensionError)); + + // TODO(dpapad): Share this logic with + // chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc. + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, + base::BindOnce(&base::ComputeDirectorySize, extension->path()), + base::BindOnce( + &DeveloperPrivateGetExtensionSizeFunction::OnSizeCalculated, + this /* refcounted */)); + + return RespondLater(); +} + +void DeveloperPrivateGetExtensionSizeFunction::OnSizeCalculated( + int64_t size_in_bytes) { + base::string16 response; + + const int one_mebibyte_in_bytes = 1024 * 1024; + if (size_in_bytes < one_mebibyte_in_bytes) { + response = l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_SIZE_SMALL_LABEL); + } else { + response = + ui::FormatBytesWithUnits(size_in_bytes, ui::DATA_UNITS_MEBIBYTE, true); + } + Respond(OneArgument(std::make_unique<base::Value>(response))); +} + DeveloperPrivateGetItemsInfoFunction::DeveloperPrivateGetItemsInfoFunction() {} DeveloperPrivateGetItemsInfoFunction::~DeveloperPrivateGetItemsInfoFunction() {} @@ -821,7 +864,7 @@ // Balanced in ClearObservers(), which is called from the first observer // method to be called with the appropriate extension (or shutdown). AddRef(); - error_reporter_observer_.Add(ExtensionErrorReporter::GetInstance()); + error_reporter_observer_.Add(LoadErrorReporter::GetInstance()); registry_observer_.Add(ExtensionRegistry::Get(browser_context())); return RespondLater();
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.h b/chrome/browser/extensions/api/developer_private/developer_private_api.h index 454d4a2..4ef3918 100644 --- a/chrome/browser/extensions/api/developer_private/developer_private_api.h +++ b/chrome/browser/extensions/api/developer_private/developer_private_api.h
@@ -16,9 +16,9 @@ #include "chrome/browser/extensions/api/developer_private/entry_picker.h" #include "chrome/browser/extensions/chrome_extension_function.h" #include "chrome/browser/extensions/error_console/error_console.h" -#include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/extensions/extension_management.h" #include "chrome/browser/extensions/extension_uninstall_dialog.h" +#include "chrome/browser/extensions/load_error_reporter.h" #include "chrome/browser/extensions/pack_extension_job.h" #include "chrome/common/extensions/api/developer_private.h" #include "chrome/common/extensions/webstore_install_result.h" @@ -348,6 +348,22 @@ DISALLOW_COPY_AND_ASSIGN(DeveloperPrivateGetExtensionInfoFunction); }; +class DeveloperPrivateGetExtensionSizeFunction + : public DeveloperPrivateAPIFunction { + public: + DeveloperPrivateGetExtensionSizeFunction(); + DECLARE_EXTENSION_FUNCTION("developerPrivate.getExtensionSize", + DEVELOPERPRIVATE_GETEXTENSIONSIZE); + + private: + ~DeveloperPrivateGetExtensionSizeFunction() override; + ResponseAction Run() override; + + void OnSizeCalculated(int64_t size_in_bytes); + + DISALLOW_COPY_AND_ASSIGN(DeveloperPrivateGetExtensionSizeFunction); +}; + class DeveloperPrivateGetProfileConfigurationFunction : public DeveloperPrivateAPIFunction { public: @@ -383,7 +399,7 @@ class DeveloperPrivateReloadFunction : public DeveloperPrivateAPIFunction, public ExtensionRegistryObserver, - public ExtensionErrorReporter::Observer { + public LoadErrorReporter::Observer { public: DECLARE_EXTENSION_FUNCTION("developerPrivate.reload", DEVELOPERPRIVATE_RELOAD); @@ -395,7 +411,7 @@ const Extension* extension) override; void OnShutdown(ExtensionRegistry* registry) override; - // ExtensionErrorReporter::Observer: + // LoadErrorReporter::Observer: void OnLoadFailure(content::BrowserContext* browser_context, const base::FilePath& file_path, const std::string& error) override; @@ -421,7 +437,7 @@ ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> registry_observer_; - ScopedObserver<ExtensionErrorReporter, ExtensionErrorReporter::Observer> + ScopedObserver<LoadErrorReporter, LoadErrorReporter::Observer> error_reporter_observer_; DISALLOW_COPY_AND_ASSIGN(DeveloperPrivateReloadFunction);
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc index c077c99..7b64d05 100644 --- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc +++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
@@ -109,7 +109,9 @@ const chromeos::attestation::AttestationFlow::CertificateCallback& callback) { base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(callback, true, "certificate")); + FROM_HERE, + base::BindOnce(callback, chromeos::attestation::ATTESTATION_SUCCESS, + "certificate")); } void GetCertificateCallbackFalse( @@ -120,7 +122,10 @@ const chromeos::attestation::AttestationFlow::CertificateCallback& callback) { base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(callback, false, "")); + FROM_HERE, + base::BindOnce(callback, + chromeos::attestation::ATTESTATION_UNSPECIFIED_FAILURE, + "")); } class EPKChallengeKeyTestBase : public BrowserWithTestWindowTest {
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc index 6584caa..7a5f1b4b 100644 --- a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc +++ b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc
@@ -278,9 +278,9 @@ void EPKPChallengeKeyBase::GetCertificateCallback( const base::Callback<void(PrepareKeyResult)>& callback, - bool success, + chromeos::attestation::AttestationStatus status, const std::string& pem_certificate_chain) { - if (!success) { + if (status != chromeos::attestation::ATTESTATION_SUCCESS) { callback.Run(PREPARE_KEY_GET_CERTIFICATE_FAILED); return; }
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h index 61ab6b36d..a80e5d5 100644 --- a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h +++ b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h
@@ -151,7 +151,7 @@ bool result); void GetCertificateCallback( const base::Callback<void(PrepareKeyResult)>& callback, - bool success, + chromeos::attestation::AttestationStatus status, const std::string& pem_certificate_chain); chromeos::InstallAttributes* install_attributes_;
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc index 748d1f8..f81fd5c 100644 --- a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc +++ b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc
@@ -111,10 +111,12 @@ const chromeos::attestation::AttestationFlow::CertificateCallback& callback) { base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(callback, true, "certificate")); + FROM_HERE, + base::BindRepeating(callback, chromeos::attestation::ATTESTATION_SUCCESS, + "certificate")); } -void GetCertificateCallbackFalse( +void GetCertificateCallbackUnspecifiedFailure( chromeos::attestation::AttestationCertificateProfile certificate_profile, const AccountId& account_id, const std::string& request_origin, @@ -122,7 +124,24 @@ const chromeos::attestation::AttestationFlow::CertificateCallback& callback) { base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(callback, false, "")); + FROM_HERE, + base::BindRepeating( + callback, chromeos::attestation::ATTESTATION_UNSPECIFIED_FAILURE, + "")); +} + +void GetCertificateCallbackBadRequestFailure( + chromeos::attestation::AttestationCertificateProfile certificate_profile, + const AccountId& account_id, + const std::string& request_origin, + bool force_new_key, + const chromeos::attestation::AttestationFlow::CertificateCallback& + callback) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindRepeating( + callback, + chromeos::attestation::ATTESTATION_SERVER_BAD_REQUEST_FAILURE, "")); } class EPKPChallengeKeyTestBase : public BrowserWithTestWindowTest { @@ -279,7 +298,7 @@ TEST_F(EPKPChallengeMachineKeyTest, GetCertificateFailed) { EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, _)) - .WillRepeatedly(Invoke(GetCertificateCallbackFalse)); + .WillRepeatedly(Invoke(GetCertificateCallbackUnspecifiedFailure)); EXPECT_EQ(GetCertificateError(kGetCertificateFailed), utils::RunFunctionAndReturnError(func_.get(), kArgs, browser())); @@ -430,9 +449,17 @@ utils::RunFunctionAndReturnError(func_.get(), kArgs, browser())); } -TEST_F(EPKPChallengeUserKeyTest, GetCertificateFailed) { +TEST_F(EPKPChallengeUserKeyTest, GetCertificateFailedWithUnspecifiedFailure) { EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, _)) - .WillRepeatedly(Invoke(GetCertificateCallbackFalse)); + .WillRepeatedly(Invoke(GetCertificateCallbackUnspecifiedFailure)); + + EXPECT_EQ(GetCertificateError(kGetCertificateFailed), + utils::RunFunctionAndReturnError(func_.get(), kArgs, browser())); +} + +TEST_F(EPKPChallengeUserKeyTest, GetCertificateFailedWithBadRequestFailure) { + EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, _)) + .WillRepeatedly(Invoke(GetCertificateCallbackBadRequestFailure)); EXPECT_EQ(GetCertificateError(kGetCertificateFailed), utils::RunFunctionAndReturnError(func_.get(), kArgs, browser()));
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc index dedf48b0..254c7b0d 100644 --- a/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc +++ b/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
@@ -25,8 +25,8 @@ #include "ui/base/ime/chromeos/extension_ime_util.h" #include "ui/base/ime/chromeos/input_method_manager.h" #include "ui/base/ime/ime_engine_handler_interface.h" +#include "ui/keyboard/content/keyboard_content_util.h" #include "ui/keyboard/keyboard_controller.h" -#include "ui/keyboard/keyboard_util.h" namespace input_ime = extensions::api::input_ime; namespace DeleteSurroundingText =
diff --git a/chrome/browser/extensions/api/tab_capture/offscreen_tab.cc b/chrome/browser/extensions/api/tab_capture/offscreen_tab.cc index b72d0a9..f6e1c50 100644 --- a/chrome/browser/extensions/api/tab_capture/offscreen_tab.cc +++ b/chrome/browser/extensions/api/tab_capture/offscreen_tab.cc
@@ -5,23 +5,22 @@ #include "chrome/browser/extensions/api/tab_capture/offscreen_tab.h" #include <algorithm> +#include <utility> #include <vector> #include "base/bind.h" -#include "base/lazy_instance.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/stl_util.h" #include "chrome/browser/extensions/api/tab_capture/tab_capture_registry.h" +#include "chrome/browser/media/router/presentation_navigation_policy.h" #include "chrome/browser/media/router/receiver_presentation_service_delegate_impl.h" // nogncheck #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/web_contents_sizer.h" #include "content/public/browser/keyboard_event_processing_result.h" #include "content/public/browser/navigation_handle.h" -#include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents.h" -#include "content/public/common/web_preferences.h" #include "extensions/browser/extension_host.h" #include "extensions/browser/process_manager.h" #include "third_party/WebKit/public/web/WebPresentationReceiverFlags.h" @@ -41,10 +40,6 @@ const int kMaxSecondsToWaitForCapture = 60; const int kPollIntervalInSeconds = 1; -typedef std::vector<content::BrowserContext*> BrowserContextList; -static base::LazyInstance<BrowserContextList>::Leaky g_offscreen_profiles = - LAZY_INSTANCE_INITIALIZER; - } // namespace namespace extensions { @@ -64,13 +59,6 @@ return FromWebContents(extension_web_contents); } -// static -bool OffscreenTabsOwner::IsOffscreenProfile(const Profile* profile) { - const BrowserContextList& offscreen_profiles = g_offscreen_profiles.Get(); - return std::find(offscreen_profiles.begin(), offscreen_profiles.end(), - profile) != offscreen_profiles.end(); -} - OffscreenTab* OffscreenTabsOwner::OpenNewTab( const GURL& start_url, const gfx::Size& initial_size, @@ -98,48 +86,23 @@ } } -// Navigation policy for presentations, where top-level navigations are not -// allowed. -class OffscreenTab::PresentationNavigationPolicy - : public OffscreenTab::NavigationPolicy { - public: - PresentationNavigationPolicy() : first_navigation_started_(false) {} - ~PresentationNavigationPolicy() override = default; - - private: - // OffscreenTab::NavigationPolicy overrides - bool DidStartNavigation(content::NavigationHandle* navigation_handle) final { - // We only care about top-level navigations that are cross-document. - if (!navigation_handle->IsInMainFrame() || - navigation_handle->IsSameDocument()) { - return true; - } - - // The initial navigation had already begun. - if (first_navigation_started_) - return false; - - first_navigation_started_ = true; - return true; - } - - bool first_navigation_started_; -}; - OffscreenTab::OffscreenTab(OffscreenTabsOwner* owner) : owner_(owner), - profile_(Profile::FromBrowserContext( - owner->extension_web_contents()->GetBrowserContext()) - ->CreateOffTheRecordProfile()), + otr_profile_registration_( + IndependentOTRProfileManager::GetInstance() + ->CreateFromOriginalProfile( + Profile::FromBrowserContext( + owner->extension_web_contents()->GetBrowserContext()), + base::BindOnce(&OffscreenTab::DieIfOriginalProfileDestroyed, + base::Unretained(this)))), capture_poll_timer_(false, false), content_capture_was_detected_(false), - navigation_policy_(new NavigationPolicy) { - DCHECK(profile_); - g_offscreen_profiles.Get().push_back(profile_.get()); + navigation_policy_( + std::make_unique<media_router::DefaultNavigationPolicy>()) { + DCHECK(otr_profile_registration_->profile()); } OffscreenTab::~OffscreenTab() { - base::Erase(g_offscreen_profiles.Get(), profile_.get()); DVLOG(1) << "Destroying OffscreenTab for start_url=" << start_url_.spec(); } @@ -152,7 +115,7 @@ << initial_size.ToString() << " for start_url=" << start_url_.spec(); // Create the WebContents to contain the off-screen tab's page. - WebContents::CreateParams params(profile_.get()); + WebContents::CreateParams params(otr_profile_registration_->profile()); if (!optional_presentation_id.empty()) params.starting_sandbox_flags = blink::kPresentationReceiverSandboxFlags; @@ -182,17 +145,11 @@ media_router::ReceiverPresentationServiceDelegateImpl::CreateForWebContents( offscreen_tab_web_contents_.get(), optional_presentation_id); - if (auto* render_view_host = - offscreen_tab_web_contents_->GetRenderViewHost()) { - auto web_prefs = render_view_host->GetWebkitPreferences(); - web_prefs.presentation_receiver = true; - render_view_host->UpdateWebkitPreferences(web_prefs); - } - // Presentations are not allowed to perform top-level navigations after // initial load. This is enforced through sandboxing flags, but we also // enforce it here. - navigation_policy_.reset(new PresentationNavigationPolicy); + navigation_policy_ = + std::make_unique<media_router::PresentationNavigationPolicy>(); } // Navigate to the initial URL. @@ -411,22 +368,13 @@ void OffscreenTab::DidStartNavigation( content::NavigationHandle* navigation_handle) { DCHECK(offscreen_tab_web_contents_.get()); - if (!navigation_policy_->DidStartNavigation(navigation_handle)) { + if (!navigation_policy_->AllowNavigation(navigation_handle)) { DVLOG(2) << "Closing because NavigationPolicy disallowed " << "StartNavigation to " << navigation_handle->GetURL().spec(); Close(); } } -// Default navigation policy. -OffscreenTab::NavigationPolicy::NavigationPolicy() = default; -OffscreenTab::NavigationPolicy::~NavigationPolicy() = default; - -bool OffscreenTab::NavigationPolicy::DidStartNavigation( - content::NavigationHandle* navigation_handle) { - return true; -} - void OffscreenTab::DieIfContentCaptureEnded() { DCHECK(offscreen_tab_web_contents_.get()); @@ -464,4 +412,9 @@ base::Unretained(this))); } +void OffscreenTab::DieIfOriginalProfileDestroyed(Profile* profile) { + DCHECK(profile == otr_profile_registration_->profile()); + owner_->DestroyTab(this); +} + } // namespace extensions
diff --git a/chrome/browser/extensions/api/tab_capture/offscreen_tab.h b/chrome/browser/extensions/api/tab_capture/offscreen_tab.h index d2a56af9..0860e2e 100644 --- a/chrome/browser/extensions/api/tab_capture/offscreen_tab.h +++ b/chrome/browser/extensions/api/tab_capture/offscreen_tab.h
@@ -7,18 +7,22 @@ #include <stdint.h> +#include <memory> #include <string> #include <vector> #include "base/macros.h" #include "base/time/time.h" #include "base/timer/timer.h" +#include "chrome/browser/media/router/independent_otr_profile_manager.h" #include "content/public/browser/web_contents_delegate.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" #include "ui/gfx/geometry/size.h" -class Profile; +namespace media_router { +class NavigationPolicy; +} // namespace media_router namespace extensions { @@ -44,10 +48,6 @@ // background page's WebContents. Never returns nullptr. static OffscreenTabsOwner* Get(content::WebContents* extension_web_contents); - // Returns |true| if |profile| is associated with an offscreen tab, false - // otherwise. - static bool IsOffscreenProfile(const Profile* profile); - // Instantiate a new offscreen tab and navigate it to |start_url|. The new // tab's main frame will start out with the given |initial_size| in DIP // coordinates. If too many offscreen tabs are already running, nothing @@ -56,10 +56,9 @@ // If |optional_presentation_id| is non-empty, the offscreen tab is registered // for use by the Media Router (chrome/browser/media/router/...) as the // receiving browsing context for the W3C Presentation API. - OffscreenTab* OpenNewTab( - const GURL& start_url, - const gfx::Size& initial_size, - const std::string& optional_presentation_id); + OffscreenTab* OpenNewTab(const GURL& start_url, + const gfx::Size& initial_size, + const std::string& optional_presentation_id); protected: friend class OffscreenTab; @@ -180,28 +179,16 @@ void DidStartNavigation(content::NavigationHandle* navigation_handle) final; private: - bool in_fullscreen_mode() const { - return !non_fullscreen_size_.IsEmpty(); - } - - // Selected calls to the navigation methods in WebContentsObserver are - // delegated to this object to determine a navigation is allowed. If any - // call returns false, the offscreen tab is destroyed. The default policy - // allows all navigations. - class NavigationPolicy { - public: - NavigationPolicy(); - virtual ~NavigationPolicy(); - virtual bool DidStartNavigation( - content::NavigationHandle* navigation_handle); - }; - - class PresentationNavigationPolicy; // Forward declaration + bool in_fullscreen_mode() const { return !non_fullscreen_size_.IsEmpty(); } // Called by |capture_poll_timer_| to automatically destroy this OffscreenTab // when the capturer count returns to zero. void DieIfContentCaptureEnded(); + // Called if the profile that our OTR profile is based on is being destroyed + // and |this| therefore needs to be destroyed also. + void DieIfOriginalProfileDestroyed(Profile* profile); + OffscreenTabsOwner* const owner_; // The initial navigation URL, which may or may not match the current URL if @@ -210,7 +197,8 @@ // A non-shared off-the-record profile based on the profile of the extension // background page. - const std::unique_ptr<Profile> profile_; + const std::unique_ptr<IndependentOTRProfileManager::OTRProfileRegistration> + otr_profile_registration_; // The WebContents containing the off-screen tab's page. std::unique_ptr<content::WebContents> offscreen_tab_web_contents_; @@ -236,7 +224,7 @@ bool content_capture_was_detected_; // Object consulted to determine which offscreen tab navigations are allowed. - std::unique_ptr<NavigationPolicy> navigation_policy_; + std::unique_ptr<media_router::NavigationPolicy> navigation_policy_; DISALLOW_COPY_AND_ASSIGN(OffscreenTab); };
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.cc b/chrome/browser/extensions/api/tabs/tabs_api.cc index 107739b..8e9a546 100644 --- a/chrome/browser/extensions/api/tabs/tabs_api.cc +++ b/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -99,6 +99,7 @@ #include "ash/public/cpp/window_pin_type.h" #include "ash/public/cpp/window_properties.h" #include "ash/public/interfaces/window_pin_type.mojom.h" +#include "chrome/browser/ui/browser_command_controller.h" #include "ui/aura/window.h" #endif @@ -598,13 +599,6 @@ Browser* new_window = new Browser(create_params); -#if defined(OS_CHROMEOS) - if (create_data && - create_data->state == windows::WINDOW_STATE_LOCKED_FULLSCREEN) { - SetWindowTrustedPinned(new_window->window(), true); - } -#endif - for (const GURL& url : urls) { NavigateParams navigate_params(new_window, url, ui::PAGE_TRANSITION_LINK); navigate_params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB; @@ -641,6 +635,16 @@ } chrome::SelectNumberedTab(new_window, 0); +#if defined(OS_CHROMEOS) + // Lock the window fullscreen only after the new tab has been created + // (otherwise the tabstrip is empty). + if (create_data && + create_data->state == windows::WINDOW_STATE_LOCKED_FULLSCREEN) { + SetWindowTrustedPinned(new_window->window(), true); + new_window->command_controller()->LockedFullscreenStateChanged(); + } +#endif + if (focused) new_window->window()->Show(); else @@ -696,10 +700,14 @@ params->update_info.state != windows::WINDOW_STATE_LOCKED_FULLSCREEN && params->update_info.state != windows::WINDOW_STATE_NONE) { SetWindowTrustedPinned(controller->window(), false); + controller->GetBrowser()->command_controller()-> + LockedFullscreenStateChanged(); } else if (!is_window_trusted_pinned && params->update_info.state == windows::WINDOW_STATE_LOCKED_FULLSCREEN) { SetWindowTrustedPinned(controller->window(), true); + controller->GetBrowser()->command_controller()-> + LockedFullscreenStateChanged(); } #endif
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc index 87627ce..e426489 100644 --- a/chrome/browser/extensions/crx_installer.cc +++ b/chrome/browser/extensions/crx_installer.cc
@@ -27,10 +27,10 @@ #include "chrome/browser/extensions/convert_user_script.h" #include "chrome/browser/extensions/convert_web_app.h" #include "chrome/browser/extensions/extension_assets_manager.h" -#include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/install_tracker.h" #include "chrome/browser/extensions/install_tracker_factory.h" +#include "chrome/browser/extensions/load_error_reporter.h" #include "chrome/browser/extensions/permissions_updater.h" #include "chrome/browser/extensions/webstore_installer.h" #include "chrome/browser/profiles/profile.h" @@ -872,9 +872,8 @@ // // TODO(aa): Need to go through unit tests and clean them up too, probably get // rid of this line. - ExtensionErrorReporter::GetInstance()->ReportError( - error.message(), - false); // Be quiet. + LoadErrorReporter::GetInstance()->ReportError(error.message(), + false); // Be quiet. if (client_) client_->OnInstallFailure(error);
diff --git a/chrome/browser/extensions/display_info_provider_chromeos_unittest.cc b/chrome/browser/extensions/display_info_provider_chromeos_unittest.cc index 11eb861..f48743c 100644 --- a/chrome/browser/extensions/display_info_provider_chromeos_unittest.cc +++ b/chrome/browser/extensions/display_info_provider_chromeos_unittest.cc
@@ -20,6 +20,7 @@ #include "chrome/browser/extensions/display_info_provider_chromeos.h" #include "chrome/browser/ui/ash/tablet_mode_client.h" #include "extensions/common/api/system_display.h" +#include "services/ui/public/cpp/input_devices/input_device_client_test_api.h" #include "ui/display/display.h" #include "ui/display/display_layout.h" #include "ui/display/display_switches.h" @@ -28,8 +29,8 @@ #include "ui/display/manager/display_manager.h" #include "ui/display/test/display_manager_test_api.h" #include "ui/display/types/display_constants.h" -#include "ui/events/devices/input_device_manager.h" #include "ui/events/devices/touch_device_transform.h" +#include "ui/events/devices/touchscreen_device.h" #include "ui/gfx/geometry/rect.h" namespace extensions { @@ -42,8 +43,7 @@ ui::TouchscreenDevice touchdevice( 123, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, std::string("test external touch device"), gfx::Size(1000, 1000), 1); - ui::InputDeviceManager::GetInstance()->SetTouchscreenDevicesForTesting( - {touchdevice}); + ui::InputDeviceClientTestApi().SetTouchscreenDevices({touchdevice}); std::vector<ui::TouchDeviceTransform> transforms; ui::TouchDeviceTransform touch_device_transform; @@ -1484,7 +1484,7 @@ ? display_id_list[1] : display_id_list[0]; - ui::InputDeviceManager::GetInstance()->SetTouchscreenDevicesForTesting({}); + ui::InputDeviceClientTestApi().SetTouchscreenDevices({}); std::string id = base::Int64ToString(display_id); std::string error;
diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc index 14cafdf..7aae360 100644 --- a/chrome/browser/extensions/extension_browsertest.cc +++ b/chrome/browser/extensions/extension_browsertest.cc
@@ -27,11 +27,11 @@ #include "chrome/browser/extensions/component_loader.h" #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/extension_creator.h" -#include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/extension_install_prompt_show_params.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_util.h" +#include "chrome/browser/extensions/load_error_reporter.h" #include "chrome/browser/extensions/unpacked_installer.h" #include "chrome/browser/extensions/updater/extension_cache_fake.h" #include "chrome/browser/extensions/updater/extension_updater.h" @@ -509,7 +509,7 @@ VLOG(1) << "Errors follow:"; const std::vector<base::string16>* errors = - ExtensionErrorReporter::GetInstance()->GetErrors(); + extensions::LoadErrorReporter::GetInstance()->GetErrors(); for (std::vector<base::string16>::const_iterator iter = errors->begin(); iter != errors->end(); ++iter) VLOG(1) << *iter;
diff --git a/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc b/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc index ac14c88..eebab8f 100644 --- a/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc +++ b/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/extensions/extension_function_test_utils.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_web_ui_override_registrar.h" +#include "chrome/browser/extensions/load_error_reporter.h" #include "chrome/browser/extensions/ntp_overridden_bubble_delegate.h" #include "chrome/browser/extensions/proxy_overridden_bubble_delegate.h" #include "chrome/browser/extensions/settings_api_bubble_delegate.h" @@ -333,7 +334,7 @@ } void Init() { - ExtensionErrorReporter::Init(true); + LoadErrorReporter::Init(true); // The two lines of magical incantation required to get the extension // service to work inside a unit test and access the extension prefs. static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile()))
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index 94426cd..ab55eb7 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc
@@ -1143,8 +1143,7 @@ // (and also, on Windows, in the registry) and this code will periodically // check that location for a .crx file, which it will then install locally if // a new version is available. -// Errors are reported through ExtensionErrorReporter. Success is not -// reported. +// Errors are reported through LoadErrorReporter. Success is not reported. void ExtensionService::CheckForExternalUpdates() { if (external_updates_disabled_for_test_) return;
diff --git a/chrome/browser/extensions/extension_service_test_base.cc b/chrome/browser/extensions/extension_service_test_base.cc index b47800dde..74eee1b4 100644 --- a/chrome/browser/extensions/extension_service_test_base.cc +++ b/chrome/browser/extensions/extension_service_test_base.cc
@@ -15,9 +15,9 @@ #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "chrome/browser/extensions/component_loader.h" -#include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/extensions/extension_garbage_collector_factory.h" #include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/load_error_reporter.h" #include "chrome/browser/extensions/shared_module_service.h" #include "chrome/browser/extensions/test_extension_system.h" #include "chrome/browser/extensions/updater/extension_updater.h" @@ -276,12 +276,12 @@ } void ExtensionServiceTestBase::SetUp() { - ExtensionErrorReporter::GetInstance()->ClearErrors(); + LoadErrorReporter::GetInstance()->ClearErrors(); } void ExtensionServiceTestBase::SetUpTestCase() { // Safe to call multiple times. - ExtensionErrorReporter::Init(false); // no noisy errors. + LoadErrorReporter::Init(false); // no noisy errors. } // These are declared in the .cc so that all inheritors don't need to know
diff --git a/chrome/browser/extensions/extension_service_test_with_install.cc b/chrome/browser/extensions/extension_service_test_with_install.cc index f8f05793..6d3de67 100644 --- a/chrome/browser/extensions/extension_service_test_with_install.cc +++ b/chrome/browser/extensions/extension_service_test_with_install.cc
@@ -9,7 +9,7 @@ #include "chrome/browser/extensions/chrome_test_extension_loader.h" #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/extension_creator.h" -#include "chrome/browser/extensions/extension_error_reporter.h" +#include "chrome/browser/extensions/load_error_reporter.h" #include "chrome/browser/profiles/profile.h" #include "content/public/browser/notification_service.h" #include "content/public/test/test_utils.h" @@ -61,7 +61,7 @@ // static std::vector<base::string16> ExtensionServiceTestWithInstall::GetErrors() { const std::vector<base::string16>* errors = - ExtensionErrorReporter::GetInstance()->GetErrors(); + LoadErrorReporter::GetInstance()->GetErrors(); std::vector<base::string16> ret_val; for (const base::string16& error : *errors) { @@ -242,7 +242,7 @@ was_update_ = false; old_name_ = ""; loaded_.clear(); - ExtensionErrorReporter::GetInstance()->ClearErrors(); + LoadErrorReporter::GetInstance()->ClearErrors(); return extension; } @@ -326,8 +326,8 @@ ASSERT_TRUE(registry()->GetExtensionById(id, ExtensionRegistry::EVERYTHING)); base::FilePath extension_path = extensions_install_dir().AppendASCII(id); EXPECT_TRUE(base::PathExists(extension_path)); - size_t pref_key_count = GetPrefKeyCount(); - EXPECT_GT(pref_key_count, 0u); + ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); + EXPECT_TRUE(prefs->GetInstalledExtensionInfo(id)); // We make a copy of the extension's id since the extension can be deleted // once it's uninstalled. @@ -341,17 +341,9 @@ EXPECT_FALSE(unloaded_id_.empty()); EXPECT_EQ(extension_id, unloaded_id_); - // Verify uninstalled state. - size_t new_pref_key_count = GetPrefKeyCount(); - if (new_pref_key_count == pref_key_count) { - ValidateIntegerPref(id, "state", - Extension::EXTERNAL_EXTENSION_UNINSTALLED); - } else { - EXPECT_EQ(new_pref_key_count, pref_key_count - 1); - } - // The extension should not be in the service anymore. EXPECT_FALSE(service()->GetInstalledExtension(extension_id)); + EXPECT_FALSE(prefs->GetInstalledExtensionInfo(extension_id)); content::RunAllTasksUntilIdle(); // The directory should be gone.
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc index 317f9d41..e8eebe4 100644 --- a/chrome/browser/extensions/extension_service_unittest.cc +++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -47,7 +47,6 @@ #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/default_apps.h" #include "chrome/browser/extensions/extension_creator.h" -#include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/extensions/extension_error_ui.h" #include "chrome/browser/extensions/extension_management_test_util.h" #include "chrome/browser/extensions/extension_service_test_base.h" @@ -61,6 +60,7 @@ #include "chrome/browser/extensions/external_provider_impl.h" #include "chrome/browser/extensions/fake_safe_browsing_database_manager.h" #include "chrome/browser/extensions/installed_loader.h" +#include "chrome/browser/extensions/load_error_reporter.h" #include "chrome/browser/extensions/pack_extension_job.h" #include "chrome/browser/extensions/pending_extension_info.h" #include "chrome/browser/extensions/pending_extension_manager.h" @@ -1154,17 +1154,16 @@ // Uninstall it and check that its killbit gets set. UninstallExtension(good_crx); - ValidateIntegerPref(good_crx, "state", - Extension::EXTERNAL_EXTENSION_UNINSTALLED); + ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); + EXPECT_TRUE(prefs->IsExternalExtensionUninstalled(good_crx)); // Try to re-install it externally. This should fail because of the killbit. info = CreateExternalExtension(good_crx, version_str, path, Manifest::EXTERNAL_PREF, Extension::NO_FLAGS); provider->UpdateOrAddExtension(std::move(info)); content::RunAllTasksUntilIdle(); - ASSERT_TRUE(NULL == service()->GetExtensionById(good_crx, false)); - ValidateIntegerPref(good_crx, "state", - Extension::EXTERNAL_EXTENSION_UNINSTALLED); + ASSERT_FALSE(service()->GetExtensionById(good_crx, false)); + EXPECT_TRUE(prefs->IsExternalExtensionUninstalled(good_crx)); std::string newer_version = "1.0.0.1"; // Repeat the same thing with a newer version of the extension. @@ -1173,9 +1172,8 @@ Manifest::EXTERNAL_PREF, Extension::NO_FLAGS); provider->UpdateOrAddExtension(std::move(info)); content::RunAllTasksUntilIdle(); - ASSERT_TRUE(NULL == service()->GetExtensionById(good_crx, false)); - ValidateIntegerPref(good_crx, "state", - Extension::EXTERNAL_EXTENSION_UNINSTALLED); + ASSERT_FALSE(service()->GetExtensionById(good_crx, false)); + EXPECT_TRUE(prefs->IsExternalExtensionUninstalled(good_crx)); // Try adding the same extension from an external update URL. ASSERT_FALSE(service()->pending_extension_manager()->AddFromExternalUpdateUrl( @@ -1314,7 +1312,7 @@ installed_ = NULL; was_update_ = false; loaded_.clear(); - ExtensionErrorReporter::GetInstance()->ClearErrors(); + extensions::LoadErrorReporter::GetInstance()->ClearErrors(); } // Extensions don't install during shutdown. @@ -5060,7 +5058,11 @@ ASSERT_EQ(1u, loaded_.size()); ASSERT_EQ(location, loaded_[0]->location()); ASSERT_EQ("1.0.0.0", loaded_[0]->version()->GetString()); - ValidatePrefKeyCount(1); + ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); + EXPECT_TRUE(prefs->GetInstalledExtensionInfo(good_crx)); + // TODO(devlin): Testing the underlying values of the prefs for extensions + // should be done in an ExtensionPrefs test, not here. This should only be + // using the public ExtensionPrefs interfaces. ValidateIntegerPref(good_crx, "state", Extension::ENABLED); ValidateIntegerPref(good_crx, "location", location); @@ -5071,7 +5073,7 @@ content::RunAllTasksUntilIdle(); ASSERT_EQ(0u, GetErrors().size()); ASSERT_EQ(1u, loaded_.size()); - ValidatePrefKeyCount(1); + EXPECT_TRUE(prefs->GetInstalledExtensionInfo(good_crx)); ValidateIntegerPref(good_crx, "state", Extension::ENABLED); ValidateIntegerPref(good_crx, "location", location); @@ -5084,13 +5086,14 @@ ASSERT_EQ(0u, GetErrors().size()); ASSERT_EQ(1u, loaded_.size()); ASSERT_EQ("1.0.0.1", loaded_[0]->version()->GetString()); - ValidatePrefKeyCount(1); + EXPECT_TRUE(prefs->GetInstalledExtensionInfo(good_crx)); ValidateIntegerPref(good_crx, "state", Extension::ENABLED); ValidateIntegerPref(good_crx, "location", location); // Uninstall the extension and reload. Nothing should happen because the // preference should prevent us from reinstalling. std::string id = loaded_[0]->id(); + EXPECT_EQ(id, good_crx); bool no_uninstall = GetManagementPolicy()->MustRemainEnabled(loaded_[0].get(), NULL); service()->UninstallExtension(id, @@ -5102,6 +5105,8 @@ if (no_uninstall) { // Policy controlled extensions should not have been touched by uninstall. ASSERT_TRUE(base::PathExists(install_path)); + EXPECT_TRUE(prefs->GetInstalledExtensionInfo(good_crx)); + EXPECT_FALSE(prefs->IsExternalExtensionUninstalled(good_crx)); } else { // The extension should also be gone from the install directory. ASSERT_FALSE(base::PathExists(install_path)); @@ -5109,19 +5114,18 @@ service()->CheckForExternalUpdates(); content::RunAllTasksUntilIdle(); ASSERT_EQ(0u, loaded_.size()); - ValidatePrefKeyCount(1); - ValidateIntegerPref(good_crx, "state", - Extension::EXTERNAL_EXTENSION_UNINSTALLED); - ValidateIntegerPref(good_crx, "location", location); + EXPECT_TRUE(prefs->IsExternalExtensionUninstalled(good_crx)); + EXPECT_FALSE(prefs->GetInstalledExtensionInfo(good_crx)); // Now clear the preference and reinstall. - SetPrefInteg(good_crx, "state", Extension::ENABLED); + prefs->ClearExternalUninstallForTesting(good_crx); loaded_.clear(); WaitForExternalExtensionInstalled(); ASSERT_EQ(1u, loaded_.size()); } - ValidatePrefKeyCount(1); + EXPECT_TRUE(prefs->GetInstalledExtensionInfo(good_crx)); + EXPECT_FALSE(prefs->IsExternalExtensionUninstalled(good_crx)); ValidateIntegerPref(good_crx, "state", Extension::ENABLED); ValidateIntegerPref(good_crx, "location", location); @@ -5136,7 +5140,8 @@ service()->OnExternalProviderReady(provider); content::RunAllTasksUntilIdle(); ASSERT_EQ(0u, loaded_.size()); - ValidatePrefKeyCount(0); + EXPECT_FALSE(prefs->IsExternalExtensionUninstalled(good_crx)); + EXPECT_FALSE(prefs->GetInstalledExtensionInfo(good_crx)); // The extension should also be gone from the install directory. ASSERT_FALSE(base::PathExists(install_path)); @@ -5165,7 +5170,9 @@ service()->ReloadExtensionsForTest(); content::RunAllTasksUntilIdle(); ASSERT_EQ(0u, loaded_.size()); - ValidatePrefKeyCount(1); + + EXPECT_FALSE(prefs->GetInstalledExtensionInfo(good_crx)); + EXPECT_TRUE(prefs->IsExternalExtensionUninstalled(good_crx)); EXPECT_EQ(5, provider->visit_count()); } @@ -5704,7 +5711,7 @@ content::PluginService::GetInstance()->Init(); #endif - ExtensionErrorReporter::Init(false); // no noisy errors + extensions::LoadErrorReporter::Init(false); // no noisy errors ExtensionsReadyRecorder recorder; std::unique_ptr<TestingProfile> profile(new TestingProfile()); std::unique_ptr<base::CommandLine> command_line;
diff --git a/chrome/browser/extensions/extension_system_impl.cc b/chrome/browser/extensions/extension_system_impl.cc index bbe92a7d..5086041 100644 --- a/chrome/browser/extensions/extension_system_impl.cc +++ b/chrome/browser/extensions/extension_system_impl.cc
@@ -22,13 +22,13 @@ #include "chrome/browser/extensions/chrome_content_verifier_delegate.h" #include "chrome/browser/extensions/component_loader.h" #include "chrome/browser/extensions/crx_installer.h" -#include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/extensions/extension_garbage_collector.h" #include "chrome/browser/extensions/extension_management.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_sync_service.h" #include "chrome/browser/extensions/extension_system_factory.h" #include "chrome/browser/extensions/install_verifier.h" +#include "chrome/browser/extensions/load_error_reporter.h" #include "chrome/browser/extensions/navigation_observer.h" #include "chrome/browser/extensions/shared_module_service.h" #include "chrome/browser/extensions/shared_user_script_master.h" @@ -193,7 +193,7 @@ navigation_observer_.reset(new NavigationObserver(profile_)); bool allow_noisy_errors = !command_line->HasSwitch(switches::kNoErrorDialogs); - ExtensionErrorReporter::Init(allow_noisy_errors); + LoadErrorReporter::Init(allow_noisy_errors); content_verifier_ = new ContentVerifier( profile_, base::MakeUnique<ChromeContentVerifierDelegate>(profile_));
diff --git a/chrome/browser/extensions/installed_loader.cc b/chrome/browser/extensions/installed_loader.cc index c3951add..6ff22681 100644 --- a/chrome/browser/extensions/installed_loader.cc +++ b/chrome/browser/extensions/installed_loader.cc
@@ -17,9 +17,9 @@ #include "base/trace_event/trace_event.h" #include "base/values.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_util.h" +#include "chrome/browser/extensions/load_error_reporter.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/chrome_manifest_url_handlers.h" @@ -202,7 +202,7 @@ } if (!extension.get()) { - ExtensionErrorReporter::GetInstance()->ReportLoadError( + LoadErrorReporter::GetInstance()->ReportLoadError( info.extension_path, error, extension_service_->profile(), false); // Be quiet. return; @@ -298,11 +298,9 @@ if (!extension.get() || extension->id() != info->extension_id) { invalid_extensions_.insert(info->extension_path); - ExtensionErrorReporter::GetInstance()->ReportLoadError( - info->extension_path, - error, - profile, - false); // Be quiet. + LoadErrorReporter::GetInstance()->ReportLoadError(info->extension_path, + error, profile, + false); // Be quiet. continue; }
diff --git a/chrome/browser/extensions/extension_error_reporter.cc b/chrome/browser/extensions/load_error_reporter.cc similarity index 73% rename from chrome/browser/extensions/extension_error_reporter.cc rename to chrome/browser/extensions/load_error_reporter.cc index 320fbd01..85e26a2c 100644 --- a/chrome/browser/extensions/extension_error_reporter.cc +++ b/chrome/browser/extensions/load_error_reporter.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/extensions/extension_error_reporter.h" +#include "chrome/browser/extensions/load_error_reporter.h" #include "build/build_config.h" @@ -20,30 +20,32 @@ #include "extensions/browser/notification_types.h" #include "ui/base/l10n/l10n_util.h" -ExtensionErrorReporter* ExtensionErrorReporter::instance_ = NULL; +namespace extensions { + +LoadErrorReporter* LoadErrorReporter::instance_ = nullptr; // static -void ExtensionErrorReporter::Init(bool enable_noisy_errors) { +void LoadErrorReporter::Init(bool enable_noisy_errors) { if (!instance_) { - instance_ = new ExtensionErrorReporter(enable_noisy_errors); + instance_ = new LoadErrorReporter(enable_noisy_errors); } } // static -ExtensionErrorReporter* ExtensionErrorReporter::GetInstance() { +LoadErrorReporter* LoadErrorReporter::GetInstance() { CHECK(instance_) << "Init() was never called"; return instance_; } -ExtensionErrorReporter::ExtensionErrorReporter(bool enable_noisy_errors) +LoadErrorReporter::LoadErrorReporter(bool enable_noisy_errors) : enable_noisy_errors_(enable_noisy_errors) { if (base::ThreadTaskRunnerHandle::IsSet()) ui_task_runner_ = base::ThreadTaskRunnerHandle::Get(); } -ExtensionErrorReporter::~ExtensionErrorReporter() {} +LoadErrorReporter::~LoadErrorReporter() {} -void ExtensionErrorReporter::ReportLoadError( +void LoadErrorReporter::ReportLoadError( const base::FilePath& extension_path, const std::string& error, content::BrowserContext* browser_context, @@ -57,15 +59,14 @@ base::string16 message = base::UTF8ToUTF16(base::StringPrintf( "%s %s. %s", l10n_util::GetStringUTF8(IDS_EXTENSIONS_LOAD_ERROR_MESSAGE).c_str(), - path_str.c_str(), - error.c_str())); + path_str.c_str(), error.c_str())); ReportError(message, be_noisy); for (auto& observer : observers_) observer.OnLoadFailure(browser_context, extension_path, error); } -void ExtensionErrorReporter::ReportError(const base::string16& message, - bool be_noisy) { +void LoadErrorReporter::ReportError(const base::string16& message, + bool be_noisy) { // NOTE: There won't be a |ui_task_runner_| in the unit test environment. CHECK(!ui_task_runner_ || ui_task_runner_->BelongsToCurrentThread()) << "ReportError can only be called from the UI thread."; @@ -83,18 +84,20 @@ } } -const std::vector<base::string16>* ExtensionErrorReporter::GetErrors() { +const std::vector<base::string16>* LoadErrorReporter::GetErrors() { return &errors_; } -void ExtensionErrorReporter::ClearErrors() { +void LoadErrorReporter::ClearErrors() { errors_.clear(); } -void ExtensionErrorReporter::AddObserver(Observer* observer) { +void LoadErrorReporter::AddObserver(Observer* observer) { observers_.AddObserver(observer); } -void ExtensionErrorReporter::RemoveObserver(Observer* observer) { +void LoadErrorReporter::RemoveObserver(Observer* observer) { observers_.RemoveObserver(observer); } + +} // namespace extensions
diff --git a/chrome/browser/extensions/extension_error_reporter.h b/chrome/browser/extensions/load_error_reporter.h similarity index 77% rename from chrome/browser/extensions/extension_error_reporter.h rename to chrome/browser/extensions/load_error_reporter.h index ffb280f..24e37f9 100644 --- a/chrome/browser/extensions/extension_error_reporter.h +++ b/chrome/browser/extensions/load_error_reporter.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 CHROME_BROWSER_EXTENSIONS_EXTENSION_ERROR_REPORTER_H_ -#define CHROME_BROWSER_EXTENSIONS_EXTENSION_ERROR_REPORTER_H_ +#ifndef CHROME_BROWSER_EXTENSIONS_LOAD_ERROR_REPORTER_H_ +#define CHROME_BROWSER_EXTENSIONS_LOAD_ERROR_REPORTER_H_ #include <string> #include <vector> @@ -21,15 +21,14 @@ class BrowserContext; } +namespace extensions { + // Exposes an easy way for the various components of the extension system to -// report errors. This is a singleton that lives on the UI thread, with the +// report load errors. This is a singleton that lives on the UI thread, with the // exception of ReportError() which may be called from any thread. -// TODO(aa): Hook this up to about:extensions, when we have about:extensions. -// TODO(aa): Consider exposing directly, or via a helper, to the renderer -// process and plumbing the errors out to the browser. // TODO(aa): Add ReportError(extension_id, message, be_noisy), so that we can // report errors that are specific to a particular extension. -class ExtensionErrorReporter { +class LoadErrorReporter { public: class Observer { public: @@ -46,7 +45,7 @@ static void Init(bool enable_noisy_errors); // Get the singleton instance. - static ExtensionErrorReporter* GetInstance(); + static LoadErrorReporter* GetInstance(); // Report an extension load error. This forwards to ReportError() after // sending an EXTENSION_LOAD_ERROR notification. @@ -73,16 +72,20 @@ void RemoveObserver(Observer* observer); private: - static ExtensionErrorReporter* instance_; + static LoadErrorReporter* instance_; - explicit ExtensionErrorReporter(bool enable_noisy_errors); - ~ExtensionErrorReporter(); + explicit LoadErrorReporter(bool enable_noisy_errors); + ~LoadErrorReporter(); scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; std::vector<base::string16> errors_; bool enable_noisy_errors_; base::ObserverList<Observer> observers_; + + DISALLOW_COPY_AND_ASSIGN(LoadErrorReporter); }; -#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_ERROR_REPORTER_H_ +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_LOAD_ERROR_REPORTER_H_
diff --git a/chrome/browser/extensions/unpacked_installer.cc b/chrome/browser/extensions/unpacked_installer.cc index 543781b..2be854c 100644 --- a/chrome/browser/extensions/unpacked_installer.cc +++ b/chrome/browser/extensions/unpacked_installer.cc
@@ -14,9 +14,9 @@ #include "base/strings/utf_string_conversions.h" #include "base/task_scheduler/post_task.h" #include "base/threading/thread_restrictions.h" -#include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/extensions/extension_management.h" #include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/load_error_reporter.h" #include "chrome/browser/extensions/permissions_updater.h" #include "chrome/browser/profiles/profile.h" #include "components/crx_file/id_util.h" @@ -351,11 +351,8 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); if (service_weak_.get()) { - ExtensionErrorReporter::GetInstance()->ReportLoadError( - extension_path_, - error, - service_weak_->profile(), - be_noisy_on_failure_); + LoadErrorReporter::GetInstance()->ReportLoadError( + extension_path_, error, service_weak_->profile(), be_noisy_on_failure_); } if (!callback_.is_null()) {
diff --git a/chrome/browser/extensions/unpacked_installer.h b/chrome/browser/extensions/unpacked_installer.h index e30e6bd9..266f83a 100644 --- a/chrome/browser/extensions/unpacked_installer.h +++ b/chrome/browser/extensions/unpacked_installer.h
@@ -43,7 +43,7 @@ // Loads the extension from the directory |extension_path|, which is // the top directory of a specific extension where its manifest file lives. - // Errors are reported through ExtensionErrorReporter. On success, + // Errors are reported through LoadErrorReporter. On success, // ExtensionService::AddExtension() is called. void Load(const base::FilePath& extension_path);
diff --git a/chrome/browser/extensions/updater/extension_updater_unittest.cc b/chrome/browser/extensions/updater/extension_updater_unittest.cc index e873c40..c0a8423a 100644 --- a/chrome/browser/extensions/updater/extension_updater_unittest.cc +++ b/chrome/browser/extensions/updater/extension_updater_unittest.cc
@@ -34,7 +34,6 @@ #include "build/build_config.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/crx_installer.h" -#include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/extensions/extension_sync_data.h" #include "chrome/browser/extensions/test_extension_prefs.h" #include "chrome/browser/extensions/test_extension_service.h"
diff --git a/chrome/browser/extensions/window_open_apitest.cc b/chrome/browser/extensions/window_open_apitest.cc index 1f5cfc8..1b63334 100644 --- a/chrome/browser/extensions/window_open_apitest.cc +++ b/chrome/browser/extensions/window_open_apitest.cc
@@ -42,8 +42,10 @@ #if defined(OS_CHROMEOS) #include "ash/public/cpp/window_properties.h" #include "ash/public/interfaces/window_pin_type.mojom.h" +#include "chrome/app/chrome_command_ids.h" #include "chrome/browser/extensions/window_controller.h" #include "chrome/browser/extensions/window_controller_list.h" +#include "chrome/browser/ui/browser_command_controller.h" #include "ui/aura/window.h" #endif @@ -434,7 +436,10 @@ } IN_PROC_BROWSER_TEST_F(WindowOpenApiTest, RemoveLockedFullscreenFromWindow) { + // After locking the window, do a LockedFullscreenStateChanged so the + // command_controller state catches up as well. SetCurrentWindowPinType(ash::mojom::WindowPinType::TRUSTED_PINNED); + browser()->command_controller()->LockedFullscreenStateChanged(); ASSERT_TRUE(RunExtensionTestWithArg("locked_fullscreen/with_permission", "removeLockedFullscreenFromWindow")) @@ -444,6 +449,24 @@ EXPECT_EQ(ash::mojom::WindowPinType::NONE, GetCurrentWindowPinType()); } +// Make sure that commands disabling code works in locked fullscreen mode. +IN_PROC_BROWSER_TEST_F(WindowOpenApiTest, VerifyCommandsInLockedFullscreen) { + // IDC_EXIT is always enabled in regular mode so it's a perfect candidate for + // testing. + EXPECT_TRUE(browser()->command_controller()->IsCommandEnabled(IDC_EXIT)); + ASSERT_TRUE(RunExtensionTestWithArg("locked_fullscreen/with_permission", + "updateWindowToLockedFullscreen")) + << message_; + + // IDC_EXIT is not enabled in locked fullscreen. + EXPECT_FALSE(browser()->command_controller()->IsCommandEnabled(IDC_EXIT)); + + // Verify some whitelisted commands. + EXPECT_TRUE(browser()->command_controller()->IsCommandEnabled(IDC_COPY)); + EXPECT_TRUE(browser()->command_controller()->IsCommandEnabled(IDC_FIND)); + EXPECT_TRUE(browser()->command_controller()->IsCommandEnabled(IDC_ZOOM_PLUS)); +} + IN_PROC_BROWSER_TEST_F(WindowOpenApiTest, OpenLockedFullscreenWindowWithoutPermission) { ASSERT_TRUE(RunExtensionTestWithArg("locked_fullscreen/without_permission", @@ -471,6 +494,7 @@ IN_PROC_BROWSER_TEST_F(WindowOpenApiTest, RemoveLockedFullscreenFromWindowWithoutPermission) { SetCurrentWindowPinType(ash::mojom::WindowPinType::TRUSTED_PINNED); + browser()->command_controller()->LockedFullscreenStateChanged(); ASSERT_TRUE(RunExtensionTestWithArg("locked_fullscreen/without_permission", "removeLockedFullscreenFromWindow"))
diff --git a/chrome/browser/extensions/zipfile_installer.cc b/chrome/browser/extensions/zipfile_installer.cc index 16fd6e4..0239005 100644 --- a/chrome/browser/extensions/zipfile_installer.cc +++ b/chrome/browser/extensions/zipfile_installer.cc
@@ -7,8 +7,8 @@ #include "base/files/file_util.h" #include "base/path_service.h" #include "base/task_scheduler/post_task.h" -#include "chrome/browser/extensions/extension_error_reporter.h" #include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/load_error_reporter.h" #include "chrome/browser/extensions/unpacked_installer.h" #include "chrome/browser/profiles/profile.h" #include "chrome/grit/generated_resources.h" @@ -112,7 +112,7 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (extension_service_weak_) { - ExtensionErrorReporter::GetInstance()->ReportLoadError( + LoadErrorReporter::GetInstance()->ReportLoadError( zip_file_, error, extension_service_weak_->profile(), be_noisy_on_failure_); }
diff --git a/chrome/browser/extensions/zipfile_installer.h b/chrome/browser/extensions/zipfile_installer.h index 28d5407..587374a 100644 --- a/chrome/browser/extensions/zipfile_installer.h +++ b/chrome/browser/extensions/zipfile_installer.h
@@ -46,7 +46,7 @@ // On failure, report the |error| reason. void ReportFailure(const std::string& error); - // Passed to the ExtensionErrorReporter when reporting errors. + // Passed to the LoadErrorReporter when reporting errors. bool be_noisy_on_failure_; // Pointer to our controlling extension service.
diff --git a/chrome/browser/geolocation/geolocation_permission_context.cc b/chrome/browser/geolocation/geolocation_permission_context.cc index 1a6faa7f..e80b41e1 100644 --- a/chrome/browser/geolocation/geolocation_permission_context.cc +++ b/chrome/browser/geolocation/geolocation_permission_context.cc
@@ -11,7 +11,9 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" -#include "device/geolocation/geolocation_provider.h" +#include "content/public/common/service_manager_connection.h" +#include "services/device/public/interfaces/constants.mojom.h" +#include "services/service_manager/public/cpp/connector.h" #include "url/origin.h" GeolocationPermissionContext::GeolocationPermissionContext(Profile* profile) @@ -83,11 +85,26 @@ requesting_frame.GetOrigin(), allowed); if (allowed) { - device::GeolocationProvider::GetInstance() - ->UserDidOptIntoLocationServices(); + GetGeolocationControl()->UserDidOptIntoLocationServices(); } } bool GeolocationPermissionContext::IsRestrictedToSecureOrigins() const { return true; } + +device::mojom::GeolocationControl* +GeolocationPermissionContext::GetGeolocationControl() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (geolocation_control_) + return geolocation_control_.get(); + + auto request = mojo::MakeRequest(&geolocation_control_); + if (!content::ServiceManagerConnection::GetForProcess()) + return geolocation_control_.get(); + + service_manager::Connector* connector = + content::ServiceManagerConnection::GetForProcess()->GetConnector(); + connector->BindInterface(device::mojom::kServiceName, std::move(request)); + return geolocation_control_.get(); +}
diff --git a/chrome/browser/geolocation/geolocation_permission_context.h b/chrome/browser/geolocation/geolocation_permission_context.h index 61fcd0a..376aec7 100644 --- a/chrome/browser/geolocation/geolocation_permission_context.h +++ b/chrome/browser/geolocation/geolocation_permission_context.h
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "chrome/browser/geolocation/geolocation_permission_context_extensions.h" #include "chrome/browser/permissions/permission_context_base.h" +#include "device/geolocation/public/interfaces/geolocation_control.mojom.h" namespace content { class WebContents; @@ -42,9 +43,13 @@ bool allowed) override; bool IsRestrictedToSecureOrigins() const override; + device::mojom::GeolocationControl* GetGeolocationControl(); + // This must only be accessed from the UI thread. GeolocationPermissionContextExtensions extensions_context_; + device::mojom::GeolocationControlPtr geolocation_control_; + DISALLOW_COPY_AND_ASSIGN(GeolocationPermissionContext); };
diff --git a/chrome/browser/gpu/gl_string_manager.cc b/chrome/browser/gpu/gl_string_manager.cc deleted file mode 100644 index 3f6767c..0000000 --- a/chrome/browser/gpu/gl_string_manager.cc +++ /dev/null
@@ -1,97 +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 "chrome/browser/gpu/gl_string_manager.h" - -#include <memory> - -#include "base/command_line.h" -#include "base/memory/ptr_util.h" -#include "build/build_config.h" -#include "chrome/browser/browser_process.h" -#include "chrome/common/pref_names.h" -#include "components/prefs/pref_registry_simple.h" -#include "components/prefs/pref_service.h" -#include "content/public/browser/gpu_data_manager.h" -#include "gpu/config/gpu_switches.h" - -// static -void GpuProfileCache::RegisterPrefs(PrefRegistrySimple* registry) { - registry->RegisterStringPref(prefs::kGLVendorString, std::string()); - registry->RegisterStringPref(prefs::kGLRendererString, std::string()); - registry->RegisterStringPref(prefs::kGLVersionString, std::string()); -} - -// static -std::unique_ptr<GpuProfileCache> GpuProfileCache::Create() { - return base::MakeUnique<GLStringManager>(); -} - -GLStringManager::GLStringManager() { -} - -GLStringManager::~GLStringManager() { -} - -void GLStringManager::Initialize() { - // On MacOSX or Windows, preliminary GPUInfo is enough. -#if defined(OS_LINUX) - // We never remove this observer from GpuDataManager. - content::GpuDataManager::GetInstance()->AddObserver(this); - - PrefService* local_state = g_browser_process->local_state(); - if (!local_state) - return; - - gl_vendor_ = local_state->GetString(prefs::kGLVendorString); - gl_renderer_ = local_state->GetString(prefs::kGLRendererString); - gl_version_ = local_state->GetString(prefs::kGLVersionString); - - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - - if (command_line->HasSwitch(switches::kGpuTestingGLVendor)) { - gl_vendor_ = - command_line->GetSwitchValueASCII(switches::kGpuTestingGLVendor); - } - - if (command_line->HasSwitch(switches::kGpuTestingGLRenderer)) { - gl_renderer_ = - command_line->GetSwitchValueASCII(switches::kGpuTestingGLRenderer); - } - - if (command_line->HasSwitch(switches::kGpuTestingGLVersion)) { - gl_version_ = - command_line->GetSwitchValueASCII(switches::kGpuTestingGLVersion); - } - - if (!gl_vendor_.empty() || !gl_renderer_.empty() || !gl_version_.empty()) { - content::GpuDataManager::GetInstance()->SetGLStrings( - gl_vendor_, gl_renderer_, gl_version_); - } -#endif -} - -void GLStringManager::OnGpuInfoUpdate() { - std::string gl_vendor, gl_renderer, gl_version; - content::GpuDataManager::GetInstance()->GetGLStrings( - &gl_vendor, &gl_renderer, &gl_version); - - PrefService* local_state = g_browser_process->local_state(); - if (!local_state) - return; - - if (!gl_vendor.empty() && gl_vendor != gl_vendor_) { - gl_vendor_ = gl_vendor; - local_state->SetString(prefs::kGLVendorString, gl_vendor_); - } - if (!gl_renderer.empty() && gl_renderer != gl_renderer_) { - gl_renderer_ = gl_renderer; - local_state->SetString(prefs::kGLRendererString, gl_renderer_); - } - if (!gl_version.empty() && gl_version != gl_version_) { - gl_version_ = gl_version; - local_state->SetString(prefs::kGLVersionString, gl_version_); - } -} -
diff --git a/chrome/browser/gpu/gl_string_manager.h b/chrome/browser/gpu/gl_string_manager.h deleted file mode 100644 index c7ddb13..0000000 --- a/chrome/browser/gpu/gl_string_manager.h +++ /dev/null
@@ -1,36 +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 CHROME_BROWSER_GPU_GL_STRING_MANAGER_H_ -#define CHROME_BROWSER_GPU_GL_STRING_MANAGER_H_ - -#include <string> - -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "chrome/browser/gpu/gpu_profile_cache.h" -#include "content/public/browser/gpu_data_manager_observer.h" - -class GLStringManager : public GpuProfileCache, - public content::GpuDataManagerObserver { - public: - GLStringManager(); - ~GLStringManager() override; - - // GpuProfileCache. - void Initialize() override; - - // content::GpuDataManagerObserver - void OnGpuInfoUpdate() override; - - private: - std::string gl_vendor_; - std::string gl_renderer_; - std::string gl_version_; - - DISALLOW_COPY_AND_ASSIGN(GLStringManager); -}; - -#endif // CHROME_BROWSER_GPU_GL_STRING_MANAGER_H_ -
diff --git a/chrome/browser/gpu/gpu_driver_info_manager_android.cc b/chrome/browser/gpu/gpu_driver_info_manager_android.cc index c7f5b9e..ca69b92 100644 --- a/chrome/browser/gpu/gpu_driver_info_manager_android.cc +++ b/chrome/browser/gpu/gpu_driver_info_manager_android.cc
@@ -4,7 +4,7 @@ #include "chrome/browser/gpu/gpu_driver_info_manager_android.h" -#include <memory> +#include <string> #include "base/android/build_info.h" #include "base/memory/ptr_util.h" @@ -18,7 +18,7 @@ using base::android::BuildInfo; // static -void GpuProfileCache::RegisterPrefs(PrefRegistrySimple* registry) { +void GpuDriverInfoManager::RegisterPrefs(PrefRegistrySimple* registry) { registry->RegisterStringPref(prefs::kGLVendorString, std::string()); registry->RegisterStringPref(prefs::kGLVersionString, std::string()); registry->RegisterStringPref(prefs::kGLRendererString, std::string()); @@ -33,7 +33,7 @@ } // static -std::unique_ptr<GpuProfileCache> GpuProfileCache::Create() { +std::unique_ptr<GpuDriverInfoManager> GpuDriverInfoManager::Create() { return base::MakeUnique<GpuDriverInfoManager>(); } @@ -97,4 +97,3 @@ BuildInfo::GetInstance()->android_build_fp()); content::GpuDataManager::GetInstance()->RemoveObserver(this); } -
diff --git a/chrome/browser/gpu/gpu_driver_info_manager_android.h b/chrome/browser/gpu/gpu_driver_info_manager_android.h index 66e17c3..9bd0c382 100644 --- a/chrome/browser/gpu/gpu_driver_info_manager_android.h +++ b/chrome/browser/gpu/gpu_driver_info_manager_android.h
@@ -5,25 +5,28 @@ #ifndef CHROME_BROWSER_GPU_GPU_DRIVER_INFO_MANAGER_ANDROID_H_ #define CHROME_BROWSER_GPU_GPU_DRIVER_INFO_MANAGER_ANDROID_H_ -#include <string> +#include <memory> #include "base/compiler_specific.h" #include "base/macros.h" -#include "chrome/browser/gpu/gpu_profile_cache.h" #include "content/public/browser/gpu_data_manager_observer.h" +class PrefRegistrySimple; + // Class for managing the GPU driver information stored in profile. // On Android, collecting GPU driver information is very expensive as it needs // to create a temporary context. Caching the information in profile saves a lot // of start up cost. -class GpuDriverInfoManager : public GpuProfileCache, - public content::GpuDataManagerObserver { +class GpuDriverInfoManager : public content::GpuDataManagerObserver { public: GpuDriverInfoManager(); ~GpuDriverInfoManager() override; - // GpuProfileCache. - void Initialize() override; + static void RegisterPrefs(PrefRegistrySimple* registry); + + static std::unique_ptr<GpuDriverInfoManager> Create(); + + void Initialize(); // content::GpuDataManagerObserver void OnGpuInfoUpdate() override;
diff --git a/chrome/browser/gpu/gpu_profile_cache.h b/chrome/browser/gpu/gpu_profile_cache.h deleted file mode 100644 index 69ffdd9f..0000000 --- a/chrome/browser/gpu/gpu_profile_cache.h +++ /dev/null
@@ -1,26 +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_GPU_GPU_PROFILE_CACHE_H_ -#define CHROME_BROWSER_GPU_GPU_PROFILE_CACHE_H_ - -#include <memory> - -class PrefRegistrySimple; - -// Class for caching and initializing GPU data by storing them in local state. -class GpuProfileCache { - public: - static void RegisterPrefs(PrefRegistrySimple* registry); - - static std::unique_ptr<GpuProfileCache> Create(); - - virtual ~GpuProfileCache() {} - - // Get cached gpu data in local state and send them to GpuDataManager. - virtual void Initialize() = 0; -}; - -#endif // CHROME_BROWSER_GPU_GPU_PROFILE_CACHE_H_ -
diff --git a/chrome/browser/media/router/BUILD.gn b/chrome/browser/media/router/BUILD.gn index 2a43989..9bdabea 100644 --- a/chrome/browser/media/router/BUILD.gn +++ b/chrome/browser/media/router/BUILD.gn
@@ -47,6 +47,8 @@ "media_sinks_observer.h", "presentation_media_sinks_observer.cc", "presentation_media_sinks_observer.h", + "presentation_navigation_policy.cc", + "presentation_navigation_policy.h", "presentation_service_delegate_impl.cc", "presentation_service_delegate_impl.h", "presentation_service_delegate_observers.cc", @@ -85,6 +87,13 @@ "mojo/wired_display_media_route_provider.h", ] } + + if (!is_android) { + sources += [ + "independent_otr_profile_manager.cc", + "independent_otr_profile_manager.h", + ] + } } static_library("test_support") {
diff --git a/chrome/browser/media/router/independent_otr_profile_manager.cc b/chrome/browser/media/router/independent_otr_profile_manager.cc new file mode 100644 index 0000000..32e055a --- /dev/null +++ b/chrome/browser/media/router/independent_otr_profile_manager.cc
@@ -0,0 +1,157 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/media/router/independent_otr_profile_manager.h" + +#include <algorithm> +#include <utility> + +#include "base/logging.h" +#include "base/stl_util.h" +#include "base/threading/thread_task_runner_handle.h" +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/notification_source.h" + +using content::BrowserThread; + +IndependentOTRProfileManager::OTRProfileRegistration:: + ~OTRProfileRegistration() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + manager_->UnregisterProfile(profile_); +} + +IndependentOTRProfileManager::OTRProfileRegistration::OTRProfileRegistration( + IndependentOTRProfileManager* manager, + Profile* profile) + : manager_(manager), profile_(profile) { + DCHECK(manager_); + DCHECK(profile); + DCHECK(profile->IsOffTheRecord()); +} + +// static +IndependentOTRProfileManager* IndependentOTRProfileManager::GetInstance() { + return base::Singleton<IndependentOTRProfileManager>::get(); +} + +std::unique_ptr<IndependentOTRProfileManager::OTRProfileRegistration> +IndependentOTRProfileManager::CreateFromOriginalProfile( + Profile* profile, + ProfileDestroyedCallback callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(profile); + DCHECK(!profile->IsOffTheRecord()); + DCHECK(!callback.is_null()); + if (!HasDependentProfiles(profile)) { + registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, + content::Source<Profile>(profile)); + } + auto* otr_profile = profile->CreateOffTheRecordProfile(); + auto entry = refcounts_map_.emplace(otr_profile, 1); + auto callback_entry = + callbacks_map_.emplace(otr_profile, std::move(callback)); + DCHECK(entry.second); + DCHECK(callback_entry.second); + return base::WrapUnique(new OTRProfileRegistration(this, otr_profile)); +} + +void IndependentOTRProfileManager::OnBrowserAdded(Browser* browser) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + auto* profile = browser->profile(); + auto entry = refcounts_map_.find(profile); + if (entry != refcounts_map_.end()) { + ++entry->second; + } +} + +void IndependentOTRProfileManager::OnBrowserRemoved(Browser* browser) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + auto* profile = browser->profile(); + auto entry = refcounts_map_.find(profile); + if (entry == refcounts_map_.end()) { + return; + } + --entry->second; + if (entry->second == 0) { + // The is the last Browser that references |profile| _and_ the original + // registration that owned |profile| has already been destroyed. Since the + // owner of the registration is also responsible for the callback, there + // should be no callback at this point. + DCHECK(callbacks_map_.find(profile) == callbacks_map_.end()); + // This will be called from within ~Browser so we can't delete its profile + // immediately in case it has a (possibly indirect) dependency on the + // profile. + base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, entry->first); + auto* original_profile = entry->first->GetOriginalProfile(); + refcounts_map_.erase(entry); + if (!HasDependentProfiles(original_profile)) { + registrar_.Remove(this, chrome::NOTIFICATION_PROFILE_DESTROYED, + content::Source<Profile>(original_profile)); + } + } +} + +IndependentOTRProfileManager::IndependentOTRProfileManager() { + BrowserList::AddObserver(this); +} + +IndependentOTRProfileManager::~IndependentOTRProfileManager() { + BrowserList::RemoveObserver(this); + // This should be destroyed after all Browser objects, so any remaining + // refcounts should be due to registrations, which each have a corresponding + // callback. + DCHECK(std::all_of(refcounts_map_.begin(), refcounts_map_.end(), + [](const std::pair<Profile*, int32_t>& entry) { + return entry.second == 1; + })); + DCHECK(refcounts_map_.size() == callbacks_map_.size()); +} + +bool IndependentOTRProfileManager::HasDependentProfiles( + Profile* profile) const { + return std::find_if(refcounts_map_.begin(), refcounts_map_.end(), + [profile](const std::pair<Profile*, int32_t>& entry) { + return entry.first->GetOriginalProfile() == profile; + }) != refcounts_map_.end(); +} + +void IndependentOTRProfileManager::UnregisterProfile(Profile* profile) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + auto entry = refcounts_map_.find(profile); + DCHECK(entry != refcounts_map_.end()); + callbacks_map_.erase(profile); + --entry->second; + if (entry->second == 0) { + auto* original_profile = profile->GetOriginalProfile(); + delete entry->first; + refcounts_map_.erase(entry); + if (!HasDependentProfiles(original_profile)) { + registrar_.Remove(this, chrome::NOTIFICATION_PROFILE_DESTROYED, + content::Source<Profile>(original_profile)); + } + } +} + +void IndependentOTRProfileManager::Observe( + int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type); + for (auto it = callbacks_map_.begin(); it != callbacks_map_.end();) { + if (source != content::Source<Profile>(it->first->GetOriginalProfile())) { + ++it; + continue; + } + // If the registration is destroyed from within this callback, we don't want + // to double-erase. If it isn't, we still need to erase the callback entry. + auto* profile = it->first; + auto callback = std::move(it->second); + it = callbacks_map_.erase(it); + std::move(callback).Run(profile); + } +}
diff --git a/chrome/browser/media/router/independent_otr_profile_manager.h b/chrome/browser/media/router/independent_otr_profile_manager.h new file mode 100644 index 0000000..be9e404 --- /dev/null +++ b/chrome/browser/media/router/independent_otr_profile_manager.h
@@ -0,0 +1,106 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_MEDIA_ROUTER_INDEPENDENT_OTR_PROFILE_MANAGER_H_ +#define CHROME_BROWSER_MEDIA_ROUTER_INDEPENDENT_OTR_PROFILE_MANAGER_H_ + +#include <cstdint> +#include <memory> + +#include "base/callback.h" +#include "base/containers/flat_map.h" +#include "base/macros.h" +#include "base/memory/singleton.h" +#include "chrome/browser/ui/browser_list_observer.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" + +class Profile; + +// This class manages Profile instances that were created by +// Profile::CreateOffTheRecordProfile(). These instances are owned by this +// class, instead of the original Profile (as is normally the case), as the +// lifetime assumptions are different. +// +// Normally, the last Browser object using an OTR profile will delete that +// profile (via its original Profile) when the Browser is closed. Users of +// CreateOffTheRecordProfile can't let a Browser destroy an independently +// created OTR profile and must instead rely on this class. +// +// In particular, this functionality is used by extensions::OffscreenTab and +// PresentationReceiverWindowController (used by the Presentation API). In the +// case of offscreen tabs, there is no interaction with a Browser object outside +// of DevTools. The Presentation API reciever Windows don't necessarily have +// special lifetime requirements but they still can't use the same destruction +// path in ~Browser as the normal OTR profile. DevTools presents a similar +// problem for presentation API windows as well. +// +// Normally, the caller should own the registration and delete it if the +// original profile is destroyed. This will be signaled via the callback passed +// to CreateFromOriginalProfile if the registration is still alive when the +// original profile is being destroyed. +// +// All methods must be called on the UI thread. +class IndependentOTRProfileManager final + : public BrowserListObserver, + public content::NotificationObserver { + public: + class OTRProfileRegistration { + public: + ~OTRProfileRegistration(); + + Profile* profile() const { return profile_; } + + private: + friend class IndependentOTRProfileManager; + + OTRProfileRegistration(IndependentOTRProfileManager* manager, + Profile* profile); + + IndependentOTRProfileManager* const manager_; + Profile* const profile_; + + DISALLOW_COPY_AND_ASSIGN(OTRProfileRegistration); + }; + + using ProfileDestroyedCallback = base::OnceCallback<void(Profile*)>; + + static IndependentOTRProfileManager* GetInstance(); + + // Creates an OTR profile from |profile| and registers it with this object. + // |callback| will be called if |profile| is being destroyed. If |callback| + // is called, the registration this method returns should be destroyed. + std::unique_ptr<OTRProfileRegistration> CreateFromOriginalProfile( + Profile* profile, + ProfileDestroyedCallback callback); + + private: + friend struct base::DefaultSingletonTraits<IndependentOTRProfileManager>; + + IndependentOTRProfileManager(); + ~IndependentOTRProfileManager() final; + + bool HasDependentProfiles(Profile* profile) const; + void UnregisterProfile(Profile* profile); + + // chrome::BrowserListObserver overrides. + void OnBrowserAdded(Browser* browser) final; + void OnBrowserRemoved(Browser* browser) final; + + // content::NotificationObserver overrides. + void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) final; + + // Counts the number of Browser instances referencing an independent OTR + // profile plus 1 for the OTRProfileRegistration object that created it. + base::flat_map<Profile*, int32_t> refcounts_map_; + base::flat_map<Profile*, ProfileDestroyedCallback> callbacks_map_; + + content::NotificationRegistrar registrar_; + + DISALLOW_COPY_AND_ASSIGN(IndependentOTRProfileManager); +}; + +#endif // CHROME_BROWSER_MEDIA_ROUTER_INDEPENDENT_OTR_PROFILE_MANAGER_H_
diff --git a/chrome/browser/media/router/independent_otr_profile_manager_browsertest.cc b/chrome/browser/media/router/independent_otr_profile_manager_browsertest.cc new file mode 100644 index 0000000..266d1daf --- /dev/null +++ b/chrome/browser/media/router/independent_otr_profile_manager_browsertest.cc
@@ -0,0 +1,330 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <set> + +#include "base/files/scoped_temp_dir.h" +#include "base/run_loop.h" +#include "base/stl_util.h" +#include "base/threading/thread_restrictions.h" +#include "build/build_config.h" +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chrome/browser/media/router/independent_otr_profile_manager.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_navigator.h" +#include "chrome/browser/ui/browser_navigator_params.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/test/base/in_process_browser_test.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/notification_source.h" +#include "content/public/browser/web_contents.h" +#include "ui/base/page_transition_types.h" +#include "ui/base/window_open_disposition.h" + +namespace content { +class NotificationDetails; +} // namespace content + +namespace { + +class ProfileDestructionWatcher final : public content::NotificationObserver { + public: + using DestructionCallback = base::OnceClosure; + + ProfileDestructionWatcher() = default; + ~ProfileDestructionWatcher() override = default; + + // Watches for the destruction of |profile| and sets |destroyed| to true when + // that happens. |profile| can be any Profile object, but most tests below + // use it to watch for the cleanup of an OTR profile. + void Watch(Profile* profile, bool* destroyed) { + ASSERT_FALSE(*destroyed); + profile_ = profile; + destroyed_ = destroyed; + registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, + content::Source<Profile>(profile_)); + } + + // content::NotificationObserver overrides. + void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) override { + DCHECK_EQ(chrome::NOTIFICATION_PROFILE_DESTROYED, type); + DCHECK(content::Source<Profile>(profile_) == source); + *destroyed_ = true; + registrar_.Remove(this, chrome::NOTIFICATION_PROFILE_DESTROYED, source); + } + + private: + Profile* profile_; + bool* destroyed_; + content::NotificationRegistrar registrar_; +}; + +void OriginalProfileNeverDestroyed(Profile* profile) { + FAIL() + << "Original profile unexpectedly destroyed before dependent OTR profile"; +} + +// This class acts as an owner of an OTRProfileRegistration and deletes the +// registration when it is notified that the original profile is being +// destroyed. This is the minimum behavior expected by owners of +// OTRProfileRegistration. +class RegistrationOwner { + public: + // |profile| is an original Profile from which we are creating a registered + // OTR profile. |this| will own the resulting OTR profile registration. + RegistrationOwner(IndependentOTRProfileManager* manager, Profile* profile) + : otr_profile_registration_(manager->CreateFromOriginalProfile( + profile, + base::BindOnce(&RegistrationOwner::OriginalProfileDestroyed, + base::Unretained(this)))) {} + + Profile* profile() const { return otr_profile_registration_->profile(); } + + private: + void OriginalProfileDestroyed(Profile* profile) { + DCHECK(profile == otr_profile_registration_->profile()); + otr_profile_registration_.reset(); + } + + std::unique_ptr<IndependentOTRProfileManager::OTRProfileRegistration> + otr_profile_registration_; +}; + +} // namespace + +class IndependentOTRProfileManagerTest : public InProcessBrowserTest { + protected: + void EnableProfileHelperTestSettings() { + chromeos::ProfileHelper::Get()->SetProfileToUserForTestingEnabled(true); + chromeos::ProfileHelper::Get()->SetAlwaysReturnPrimaryUserForTesting(true); + } + + IndependentOTRProfileManager* manager_ = + IndependentOTRProfileManager::GetInstance(); +}; + +IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest, CreateAndDestroy) { + ProfileDestructionWatcher watcher; + bool destroyed = false; + { + auto profile_registration = manager_->CreateFromOriginalProfile( + browser()->profile(), base::BindOnce(&OriginalProfileNeverDestroyed)); + auto* otr_profile = profile_registration->profile(); + + ASSERT_NE(browser()->profile(), otr_profile); + EXPECT_NE(browser()->profile()->GetOffTheRecordProfile(), otr_profile); + EXPECT_TRUE(otr_profile->IsOffTheRecord()); + + watcher.Watch(otr_profile, &destroyed); + } + + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(destroyed); +} + +IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest, + DeleteWaitsForLastBrowser) { + ProfileDestructionWatcher watcher; + Profile* otr_profile = nullptr; + Browser* otr_browser1 = nullptr; + Browser* otr_browser2 = nullptr; + { + auto profile_registration = manager_->CreateFromOriginalProfile( + browser()->profile(), base::BindOnce(&OriginalProfileNeverDestroyed)); + otr_profile = profile_registration->profile(); + + otr_browser1 = CreateBrowser(otr_profile); + otr_browser2 = CreateBrowser(otr_profile); + ASSERT_NE(otr_browser1, otr_browser2); + } + + otr_browser1->window()->Close(); + base::RunLoop().RunUntilIdle(); + ASSERT_FALSE(base::ContainsValue(*BrowserList::GetInstance(), otr_browser1)); + ASSERT_TRUE(base::ContainsValue(*BrowserList::GetInstance(), otr_browser2)); + + bool destroyed = false; + watcher.Watch(otr_profile, &destroyed); + otr_browser2->window()->Close(); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(destroyed); +} + +IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest, + DeleteImmediatelyWhenBrowsersAlreadyClosed) { + ProfileDestructionWatcher watcher; + bool destroyed = false; + { + auto profile_registration = manager_->CreateFromOriginalProfile( + browser()->profile(), base::BindOnce(&OriginalProfileNeverDestroyed)); + auto* otr_profile = profile_registration->profile(); + + auto* otr_browser1 = CreateBrowser(otr_profile); + auto* otr_browser2 = CreateBrowser(otr_profile); + ASSERT_NE(otr_browser1, otr_browser2); + + otr_browser1->window()->Close(); + otr_browser2->window()->Close(); + base::RunLoop().RunUntilIdle(); + ASSERT_FALSE( + base::ContainsValue(*BrowserList::GetInstance(), otr_browser1)); + ASSERT_FALSE( + base::ContainsValue(*BrowserList::GetInstance(), otr_browser2)); + + watcher.Watch(otr_profile, &destroyed); + } + + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(destroyed); +} + +IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest, + CreateTwoFromSameProfile) { + ProfileDestructionWatcher watcher1; + ProfileDestructionWatcher watcher2; + bool destroyed1 = false; + bool destroyed2 = false; + { + auto profile_registration1 = manager_->CreateFromOriginalProfile( + browser()->profile(), base::BindOnce(&OriginalProfileNeverDestroyed)); + auto* otr_profile1 = profile_registration1->profile(); + + auto profile_registration2 = manager_->CreateFromOriginalProfile( + browser()->profile(), base::BindOnce(&OriginalProfileNeverDestroyed)); + auto* otr_profile2 = profile_registration2->profile(); + + ASSERT_NE(otr_profile1, otr_profile2); + + watcher1.Watch(otr_profile1, &destroyed1); + watcher2.Watch(otr_profile2, &destroyed2); + } + + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(destroyed1); + EXPECT_TRUE(destroyed2); +} + +IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest, + OriginalProfileDestroyedFirst) { + ProfileDestructionWatcher watcher; + + base::ScopedAllowBlockingForTesting allow_blocking; + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); +#if defined(OS_CHROMEOS) + EnableProfileHelperTestSettings(); +#endif + auto original_profile = base::WrapUnique(Profile::CreateProfile( + temp_dir.GetPath(), nullptr, Profile::CREATE_MODE_SYNCHRONOUS)); + ASSERT_TRUE(original_profile); + auto profile_owner = RegistrationOwner(manager_, original_profile.get()); + auto* otr_profile = profile_owner.profile(); + + ASSERT_NE(original_profile.get(), otr_profile); + EXPECT_NE(original_profile->GetOffTheRecordProfile(), otr_profile); + + bool destroyed = false; + watcher.Watch(otr_profile, &destroyed); + original_profile.reset(); + // |original_profile| being destroyed should trigger the dependent OTR + // profile to be destroyed. + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(destroyed); +} + +IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest, + OriginalProfileDestroyedFirstTwoOTR) { + ProfileDestructionWatcher watcher1; + ProfileDestructionWatcher watcher2; + + base::ScopedAllowBlockingForTesting allow_blocking; + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); +#if defined(OS_CHROMEOS) + EnableProfileHelperTestSettings(); +#endif + auto original_profile = base::WrapUnique(Profile::CreateProfile( + temp_dir.GetPath(), nullptr, Profile::CREATE_MODE_SYNCHRONOUS)); + ASSERT_TRUE(original_profile); + auto profile_owner1 = RegistrationOwner(manager_, original_profile.get()); + auto* otr_profile1 = profile_owner1.profile(); + + auto profile_owner2 = RegistrationOwner(manager_, original_profile.get()); + auto* otr_profile2 = profile_owner2.profile(); + + bool destroyed1 = false; + bool destroyed2 = false; + watcher1.Watch(otr_profile1, &destroyed1); + watcher2.Watch(otr_profile2, &destroyed2); + original_profile.reset(); + // |original_profile| being destroyed should trigger the dependent OTR + // profiles to be destroyed. + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(destroyed1); + EXPECT_TRUE(destroyed2); +} + +IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest, + BrowserClosingDoesntRemoveProfileObserver) { + ProfileDestructionWatcher watcher1; + ProfileDestructionWatcher watcher2; + bool destroyed1 = false; + bool destroyed2 = false; + + base::ScopedAllowBlockingForTesting allow_blocking; + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); +#if defined(OS_CHROMEOS) + EnableProfileHelperTestSettings(); +#endif + auto original_profile = base::WrapUnique(Profile::CreateProfile( + temp_dir.GetPath(), nullptr, Profile::CREATE_MODE_SYNCHRONOUS)); + ASSERT_TRUE(original_profile); + auto profile_owner1 = RegistrationOwner(manager_, original_profile.get()); + auto* otr_profile1 = profile_owner1.profile(); + Browser* otr_browser = nullptr; + { + auto profile_owner2 = RegistrationOwner(manager_, original_profile.get()); + auto* otr_profile2 = profile_owner2.profile(); + + otr_browser = CreateBrowser(otr_profile2); + watcher2.Watch(otr_profile2, &destroyed2); + } + otr_browser->window()->Close(); + base::RunLoop().RunUntilIdle(); + ASSERT_FALSE(base::ContainsValue(*BrowserList::GetInstance(), otr_browser)); + EXPECT_TRUE(destroyed2); + + watcher1.Watch(otr_profile1, &destroyed1); + original_profile.reset(); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(destroyed1); +} + +IN_PROC_BROWSER_TEST_F(IndependentOTRProfileManagerTest, + CallbackNotCalledAfterUnregister) { + ProfileDestructionWatcher watcher; + Browser* otr_browser = nullptr; + Profile* otr_profile = nullptr; + { + auto profile_registration = manager_->CreateFromOriginalProfile( + browser()->profile(), base::BindOnce(&OriginalProfileNeverDestroyed)); + otr_profile = profile_registration->profile(); + + otr_browser = CreateBrowser(otr_profile); + } + bool destroyed = false; + watcher.Watch(otr_profile, &destroyed); + otr_browser->window()->Close(); + base::RunLoop().RunUntilIdle(); + ASSERT_FALSE(base::ContainsValue(*BrowserList::GetInstance(), otr_browser)); + EXPECT_TRUE(destroyed); +}
diff --git a/chrome/browser/media/router/presentation_navigation_policy.cc b/chrome/browser/media/router/presentation_navigation_policy.cc new file mode 100644 index 0000000..1879003 --- /dev/null +++ b/chrome/browser/media/router/presentation_navigation_policy.cc
@@ -0,0 +1,40 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/media/router/presentation_navigation_policy.h" + +#include "content/public/browser/navigation_handle.h" + +namespace media_router { + +NavigationPolicy::~NavigationPolicy() = default; + +DefaultNavigationPolicy::DefaultNavigationPolicy() = default; +DefaultNavigationPolicy::~DefaultNavigationPolicy() = default; + +bool DefaultNavigationPolicy::AllowNavigation(content::NavigationHandle*) { + return true; +} + +PresentationNavigationPolicy::PresentationNavigationPolicy() = default; +PresentationNavigationPolicy::~PresentationNavigationPolicy() = default; + +bool PresentationNavigationPolicy::AllowNavigation( + content::NavigationHandle* navigation_handle) { + // We only care about top-level navigations that are cross-document. + if (!navigation_handle->IsInMainFrame() || + navigation_handle->IsSameDocument()) { + return true; + } + + // The initial navigation had already begun. + if (first_navigation_started_) { + return false; + } + + first_navigation_started_ = true; + return true; +} + +} // namespace media_router
diff --git a/chrome/browser/media/router/presentation_navigation_policy.h b/chrome/browser/media/router/presentation_navigation_policy.h new file mode 100644 index 0000000..247eceb --- /dev/null +++ b/chrome/browser/media/router/presentation_navigation_policy.h
@@ -0,0 +1,48 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_MEDIA_ROUTER_PRESENTATION_NAVIGATION_POLICY_H_ +#define CHROME_BROWSER_MEDIA_ROUTER_PRESENTATION_NAVIGATION_POLICY_H_ + +namespace content { +class NavigationHandle; +} // namespace content + +namespace media_router { + +// Selected calls to the navigation methods in WebContentsObserver are +// delegated to this object to determine whether a navigation is allowed. If +// any call returns false, the presentation tab is destroyed. +class NavigationPolicy { + public: + virtual ~NavigationPolicy(); + virtual bool AllowNavigation( + content::NavigationHandle* navigation_handle) = 0; +}; + +// This default policy allows all navigations. +class DefaultNavigationPolicy : public NavigationPolicy { + public: + DefaultNavigationPolicy(); + ~DefaultNavigationPolicy() override; + + bool AllowNavigation(content::NavigationHandle* navigation_handle) override; +}; + +// Navigation policy for presentations, where top-level navigations are not +// allowed. +class PresentationNavigationPolicy : public NavigationPolicy { + public: + PresentationNavigationPolicy(); + ~PresentationNavigationPolicy() override; + + bool AllowNavigation(content::NavigationHandle* navigation_handle) override; + + private: + bool first_navigation_started_ = false; +}; + +} // namespace media_router + +#endif // CHROME_BROWSER_MEDIA_ROUTER_PRESENTATION_NAVIGATION_POLICY_H_
diff --git a/chrome/browser/media/router/receiver_presentation_service_delegate_impl.cc b/chrome/browser/media/router/receiver_presentation_service_delegate_impl.cc index a6230a8e6..1b9a6efc 100644 --- a/chrome/browser/media/router/receiver_presentation_service_delegate_impl.cc +++ b/chrome/browser/media/router/receiver_presentation_service_delegate_impl.cc
@@ -7,6 +7,9 @@ #include "base/memory/ptr_util.h" #include "chrome/browser/media/router/local_presentation_manager.h" #include "chrome/browser/media/router/local_presentation_manager_factory.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/web_preferences.h" DEFINE_WEB_CONTENTS_USER_DATA_KEY( media_router::ReceiverPresentationServiceDelegateImpl); @@ -28,6 +31,11 @@ UserDataKey(), base::WrapUnique(new ReceiverPresentationServiceDelegateImpl( web_contents, presentation_id))); + auto* render_view_host = web_contents->GetRenderViewHost(); + DCHECK(render_view_host); + auto web_prefs = render_view_host->GetWebkitPreferences(); + web_prefs.presentation_receiver = true; + render_view_host->UpdateWebkitPreferences(web_prefs); } void ReceiverPresentationServiceDelegateImpl::AddObserver(
diff --git a/chrome/browser/media_galleries/media_file_system_registry_unittest.cc b/chrome/browser/media_galleries/media_file_system_registry_unittest.cc index 6cecb16d..e59ce45 100644 --- a/chrome/browser/media_galleries/media_file_system_registry_unittest.cc +++ b/chrome/browser/media_galleries/media_file_system_registry_unittest.cc
@@ -57,6 +57,10 @@ #include "chrome/browser/chromeos/settings/device_settings_service.h" #endif +namespace content { +class SiteInstance; +} + using content::BrowserThread; using storage_monitor::StorageInfo; using storage_monitor::StorageMonitor; @@ -202,7 +206,8 @@ content::BrowserContext* browser_context); content::RenderProcessHost* CreateRenderProcessHost( - content::BrowserContext* browser_context) const override; + content::BrowserContext* browser_context, + content::SiteInstance* site_instance) const override; private: mutable std::map<content::BrowserContext*, @@ -416,7 +421,8 @@ content::RenderProcessHost* MockProfileSharedRenderProcessHostFactory::CreateRenderProcessHost( - content::BrowserContext* browser_context) const { + content::BrowserContext* browser_context, + content::SiteInstance* site_instance) const { auto existing = rph_map_.find(browser_context); if (existing != rph_map_.end()) return existing->second.get();
diff --git a/chrome/browser/metrics/chrome_stability_metrics_provider_unittest.cc b/chrome/browser/metrics/chrome_stability_metrics_provider_unittest.cc index 387b7073..09d8da5 100644 --- a/chrome/browser/metrics/chrome_stability_metrics_provider_unittest.cc +++ b/chrome/browser/metrics/chrome_stability_metrics_provider_unittest.cc
@@ -88,7 +88,7 @@ // Owned by rph_factory. content::RenderProcessHost* host( - rph_factory->CreateRenderProcessHost(profile)); + rph_factory->CreateRenderProcessHost(profile, site_instance.get())); // Crash and abnormal termination should increment renderer crash count. content::RenderProcessHost::RendererClosedDetails crash_details( @@ -146,7 +146,7 @@ // Owned by rph_factory. content::RenderProcessHost* extension_host( - rph_factory->CreateRenderProcessHost(profile)); + rph_factory->CreateRenderProcessHost(profile, site_instance.get())); // Make the rph an extension rph. extensions::ProcessMap::Get(profile)
diff --git a/chrome/browser/offline_pages/offline_page_request_job.cc b/chrome/browser/offline_pages/offline_page_request_job.cc index 1b3a6bf..d9b66ac 100644 --- a/chrome/browser/offline_pages/offline_page_request_job.cc +++ b/chrome/browser/offline_pages/offline_page_request_job.cc
@@ -377,8 +377,7 @@ OfflinePageTabHelper::FromWebContents(web_contents); DCHECK(tab_helper); tab_helper->SetOfflinePage( - *offline_page, - offline_header, + *offline_page, offline_header, true /*is_trusted*/, network_state == NetworkState::PROHIBITIVELY_SLOW_NETWORK); *offline_file_path = offline_page->file_path;
diff --git a/chrome/browser/offline_pages/offline_page_tab_helper.cc b/chrome/browser/offline_pages/offline_page_tab_helper.cc index 9e1a33ee..5f4f5a80 100644 --- a/chrome/browser/offline_pages/offline_page_tab_helper.cc +++ b/chrome/browser/offline_pages/offline_page_tab_helper.cc
@@ -8,11 +8,13 @@ #include "base/guid.h" #include "base/logging.h" #include "base/memory/ptr_util.h" +#include "build/build_config.h" #include "chrome/browser/offline_pages/offline_page_request_job.h" #include "chrome/browser/offline_pages/prefetch/prefetch_service_factory.h" #include "chrome/browser/offline_pages/request_coordinator_factory.h" #include "components/offline_pages/core/background/request_coordinator.h" #include "components/offline_pages/core/offline_page_item.h" +#include "components/offline_pages/core/offline_store_utils.h" #include "components/offline_pages/core/prefetch/offline_metrics_collector.h" #include "components/offline_pages/core/prefetch/prefetch_service.h" #include "content/public/browser/browser_thread.h" @@ -27,14 +29,25 @@ namespace offline_pages { +namespace { +bool SchemeIsForUntrustedOfflinePages(const GURL& url) { +#if defined(OS_ANDROID) + if (url.SchemeIs(url::kContentScheme)) + return true; +#endif + return url.SchemeIsFile(); +} +} // namespace + OfflinePageTabHelper::LoadedOfflinePageInfo::LoadedOfflinePageInfo() - : is_showing_offline_preview(false) {} + : is_trusted(false), is_showing_offline_preview(false) {} OfflinePageTabHelper::LoadedOfflinePageInfo::~LoadedOfflinePageInfo() {} void OfflinePageTabHelper::LoadedOfflinePageInfo::Clear() { offline_page.reset(); offline_header.Clear(); + is_trusted = false; is_showing_offline_preview = false; } @@ -87,52 +100,83 @@ if (navigation_handle->IsSameDocument()) return; - GURL navigated_url = navigation_handle->GetURL(); - if (navigation_handle->IsErrorPage()) { - offline_info_.Clear(); - } else { - // The provisional offline info can now be committed if the navigation is - // done without error. - DCHECK(!provisional_offline_info_.offline_page || - OfflinePageUtils::EqualsIgnoringFragment( - navigated_url, - provisional_offline_info_.offline_page->url)); - offline_info_.offline_page = - std::move(provisional_offline_info_.offline_page); - offline_info_.offline_header = provisional_offline_info_.offline_header; - offline_info_.is_showing_offline_preview = - provisional_offline_info_.is_showing_offline_preview; - - // Report prefetch usage to OfflineMetricsCollector. - if (offline_info_.offline_page && - policy_controller_.IsSuggested( - offline_info_.offline_page->client_id.name_space)) { - prefetch_service_->GetOfflineMetricsCollector()->OnPrefetchedPageOpened(); - } - } + FinalizeOfflineInfo(navigation_handle); provisional_offline_info_.Clear(); + ReportPrefetchMetrics(navigation_handle); + + TryLoadingOfflinePageOnNetError(navigation_handle); +} + +void OfflinePageTabHelper::FinalizeOfflineInfo( + content::NavigationHandle* navigation_handle) { + offline_info_.Clear(); + + if (navigation_handle->IsErrorPage()) + return; + + GURL navigated_url = navigation_handle->GetURL(); + + // If a MHTML archive is being loaded for file: or content: URL, create an + // untrusted offline page. + if (SchemeIsForUntrustedOfflinePages(navigated_url) && + navigation_handle->GetWebContents()->GetContentsMimeType() == + "multipart/related") { + offline_info_.offline_page = std::make_unique<OfflinePageItem>(); + offline_info_.offline_page->offline_id = store_utils::GenerateOfflineId(); + offline_info_.is_trusted = false; + // TODO(jianli): Extract the url where the MHTML acrhive claims from the + // MHTML headers and set it in OfflinePageItem::original_url. + return; + } + + // For http/https URL,commit the provisional offline info if any. + if (!navigated_url.SchemeIsHTTPOrHTTPS() || + !provisional_offline_info_.offline_page) { + return; + } + + DCHECK(OfflinePageUtils::EqualsIgnoringFragment( + navigated_url, provisional_offline_info_.offline_page->url)); + offline_info_.offline_page = + std::move(provisional_offline_info_.offline_page); + offline_info_.offline_header = provisional_offline_info_.offline_header; + offline_info_.is_trusted = provisional_offline_info_.is_trusted; + offline_info_.is_showing_offline_preview = + provisional_offline_info_.is_showing_offline_preview; +} + +void OfflinePageTabHelper::ReportPrefetchMetrics( + content::NavigationHandle* navigation_handle) { + if (navigation_handle->IsErrorPage()) + return; + + if (!prefetch_service_) + return; + // Report the kind of navigation (online/offline) to metrics collector. // It accumulates this info to mark a day as 'offline' or 'online'. - if (!navigation_handle->IsErrorPage()) { - if (prefetch_service_) { - OfflineMetricsCollector* metrics_collector = - prefetch_service_->GetOfflineMetricsCollector(); - DCHECK(metrics_collector); + OfflineMetricsCollector* metrics_collector = + prefetch_service_->GetOfflineMetricsCollector(); + DCHECK(metrics_collector); - if (offline_page()) { - // Note that navigation to offline page may happen even if network is - // connected. For the purposes of collecting offline usage statistics, - // we still count this as offline navigation. - metrics_collector->OnSuccessfulNavigationOffline(); - } else { - metrics_collector->OnSuccessfulNavigationOnline(); - // The device is apparently online, attempt to report stats to UMA. - metrics_collector->ReportAccumulatedStats(); - } - } + if (offline_page()) { + // Report prefetch usage. + if (policy_controller_.IsSuggested(offline_page()->client_id.name_space)) + metrics_collector->OnPrefetchedPageOpened(); + // Note that navigation to offline page may happen even if network is + // connected. For the purposes of collecting offline usage statistics, + // we still count this as offline navigation. + metrics_collector->OnSuccessfulNavigationOffline(); + } else { + metrics_collector->OnSuccessfulNavigationOnline(); + // The device is apparently online, attempt to report stats to UMA. + metrics_collector->ReportAccumulatedStats(); } +} +void OfflinePageTabHelper::TryLoadingOfflinePageOnNetError( + content::NavigationHandle* navigation_handle) { // If the offline page has been loaded successfully, nothing more to do. net::Error error_code = navigation_handle->GetNetErrorCode(); if (error_code == net::OK) @@ -174,7 +218,7 @@ } OfflinePageUtils::SelectPageForURL( - web_contents()->GetBrowserContext(), navigated_url, + web_contents()->GetBrowserContext(), navigation_handle->GetURL(), URLSearchMode::SEARCH_BY_ALL_URLS, tab_id, base::Bind(&OfflinePageTabHelper::SelectPageForURLDone, weak_ptr_factory_.GetWeakPtr())); @@ -206,13 +250,19 @@ void OfflinePageTabHelper::SetOfflinePage( const OfflinePageItem& offline_page, const OfflinePageHeader& offline_header, + bool is_trusted, bool is_offline_preview) { provisional_offline_info_.offline_page = base::MakeUnique<OfflinePageItem>(offline_page); provisional_offline_info_.offline_header = offline_header; + provisional_offline_info_.is_trusted = is_trusted; provisional_offline_info_.is_showing_offline_preview = is_offline_preview; } +bool OfflinePageTabHelper::IsShowingTrustedOfflinePage() const { + return offline_info_.offline_page && offline_info_.is_trusted; +} + const OfflinePageItem* OfflinePageTabHelper::GetOfflinePageForTest() const { return provisional_offline_info_.offline_page.get(); }
diff --git a/chrome/browser/offline_pages/offline_page_tab_helper.h b/chrome/browser/offline_pages/offline_page_tab_helper.h index 0712f96..d89478d 100644 --- a/chrome/browser/offline_pages/offline_page_tab_helper.h +++ b/chrome/browser/offline_pages/offline_page_tab_helper.h
@@ -33,6 +33,7 @@ void SetOfflinePage(const OfflinePageItem& offline_page, const OfflinePageHeader& offline_header, + bool is_trusted, bool is_offline_preview); const OfflinePageItem* offline_page() { @@ -43,6 +44,9 @@ return offline_info_.offline_header; } + // Returns whether a trusted offline page is being displayed. + bool IsShowingTrustedOfflinePage() const; + // Returns nullptr if the page is not an offline preview. Returns the // OfflinePageItem related to the page if the page is an offline preview. const OfflinePageItem* GetOfflinePreviewItem() const; @@ -78,6 +82,9 @@ // The offline header that is provided when offline page is loaded. OfflinePageHeader offline_header; + // Whether the page is deemed trusted or not. + bool is_trusted; + // Whether the page is an offline preview. Offline page previews are shown // when a user's effective connection type is prohibitively slow. bool is_showing_offline_preview; @@ -93,6 +100,16 @@ void DidFinishNavigation( content::NavigationHandle* navigation_handle) override; + // Finalize the offline info when the navigation is done. + void FinalizeOfflineInfo(content::NavigationHandle* navigation_handle); + + // Report the metrics essential to PrefetchService. + void ReportPrefetchMetrics(content::NavigationHandle* navigation_handle); + + // Reload the URL in order to fetch the offline page on certain net errors. + void TryLoadingOfflinePageOnNetError( + content::NavigationHandle* navigation_handle); + void SelectPageForURLDone(const OfflinePageItem* offline_page); void DuplicateCheckDoneForScheduleDownload(
diff --git a/chrome/browser/offline_pages/offline_page_tab_helper_unittest.cc b/chrome/browser/offline_pages/offline_page_tab_helper_unittest.cc index 32eb9ce3..cb66f94 100644 --- a/chrome/browser/offline_pages/offline_page_tab_helper_unittest.cc +++ b/chrome/browser/offline_pages/offline_page_tab_helper_unittest.cc
@@ -8,6 +8,7 @@ #include "base/memory/ptr_util.h" #include "base/threading/thread_task_runner_handle.h" +#include "build/build_config.h" #include "chrome/browser/offline_pages/prefetch/prefetch_service_factory.h" #include "chrome/test/base/testing_profile.h" #include "components/offline_pages/core/offline_page_item.h" @@ -22,6 +23,13 @@ namespace { const GURL kTestPageUrl("http://mystery.site/foo.html"); +const GURL kTestFileUrl("file://foo"); + +#if defined(OS_ANDROID) +const GURL kTestContentUrl("content://foo"); +#endif + +const char kTestHeader[] = "reason=download"; } // namespace namespace offline_pages { @@ -68,6 +76,8 @@ void TearDown() override; content::BrowserContext* CreateBrowserContext() override; + void CreateNavigationSimulator(const GURL& url); + OfflinePageTabHelper* tab_helper() const { return tab_helper_; } PrefetchService* prefetch_service() const { return prefetch_service_; } content::NavigationSimulator* navigation_simulator() { @@ -98,15 +108,8 @@ prefetch_service_ = PrefetchServiceFactory::GetForBrowserContext(browser_context()); - // This initializes a nav stack inside the harness. - NavigateAndCommit(kTestPageUrl); - OfflinePageTabHelper::CreateForWebContents(web_contents()); tab_helper_ = OfflinePageTabHelper::FromWebContents(web_contents()); - - navigation_simulator_ = content::NavigationSimulator::CreateRendererInitiated( - kTestPageUrl, main_rfh()); - navigation_simulator_->SetTransition(ui::PAGE_TRANSITION_LINK); } void OfflinePageTabHelperTest::TearDown() { @@ -118,8 +121,15 @@ return builder.Build().release(); } +void OfflinePageTabHelperTest::CreateNavigationSimulator(const GURL& url) { + navigation_simulator_ = + content::NavigationSimulator::CreateBrowserInitiated(url, web_contents()); + navigation_simulator_->SetTransition(ui::PAGE_TRANSITION_LINK); +} + // Checks the test setup. TEST_F(OfflinePageTabHelperTest, InitialSetup) { + CreateNavigationSimulator(kTestPageUrl); EXPECT_NE(nullptr, tab_helper()); EXPECT_NE(nullptr, prefetch_service()); EXPECT_NE(nullptr, prefetch_service()->GetOfflineMetricsCollector()); @@ -131,6 +141,7 @@ } TEST_F(OfflinePageTabHelperTest, MetricsStartNavigation) { + CreateNavigationSimulator(kTestPageUrl); // This causes WCO::DidStartNavigation() navigation_simulator()->Start(); @@ -141,6 +152,7 @@ } TEST_F(OfflinePageTabHelperTest, MetricsOnlineNavigation) { + CreateNavigationSimulator(kTestPageUrl); navigation_simulator()->Start(); navigation_simulator()->Commit(); @@ -152,12 +164,13 @@ } TEST_F(OfflinePageTabHelperTest, MetricsOfflineNavigation) { + CreateNavigationSimulator(kTestPageUrl); navigation_simulator()->Start(); // Simulate offline interceptor loading an offline page instead. OfflinePageItem offlinePage(kTestPageUrl, 0, ClientId(), base::FilePath(), 0); OfflinePageHeader offlineHeader; - tab_helper()->SetOfflinePage(offlinePage, offlineHeader, false); + tab_helper()->SetOfflinePage(offlinePage, offlineHeader, true, false); navigation_simulator()->Commit(); @@ -168,4 +181,47 @@ EXPECT_EQ(0, metrics()->report_stats_count_); } +TEST_F(OfflinePageTabHelperTest, TrustedOfflinePage) { + CreateNavigationSimulator(kTestPageUrl); + navigation_simulator()->Start(); + + OfflinePageItem offlinePage(kTestPageUrl, 0, ClientId(), base::FilePath(), 0); + OfflinePageHeader offlineHeader(kTestHeader); + tab_helper()->SetOfflinePage(offlinePage, offlineHeader, true, false); + + navigation_simulator()->Commit(); + + ASSERT_NE(nullptr, tab_helper()->offline_page()); + EXPECT_EQ(kTestPageUrl, tab_helper()->offline_page()->url); + EXPECT_TRUE(tab_helper()->IsShowingTrustedOfflinePage()); + EXPECT_EQ(OfflinePageHeader::Reason::DOWNLOAD, + tab_helper()->offline_header().reason); +} + +TEST_F(OfflinePageTabHelperTest, UntrustedOfflinePageForFileUrl) { + CreateNavigationSimulator(kTestFileUrl); + navigation_simulator()->Start(); + navigation_simulator()->SetContentsMimeType("multipart/related"); + navigation_simulator()->Commit(); + + ASSERT_NE(nullptr, tab_helper()->offline_page()); + EXPECT_FALSE(tab_helper()->IsShowingTrustedOfflinePage()); + EXPECT_EQ(OfflinePageHeader::Reason::NONE, + tab_helper()->offline_header().reason); +} + +#if defined(OS_ANDROID) +TEST_F(OfflinePageTabHelperTest, UntrustedOfflinePageForContentUrl) { + CreateNavigationSimulator(kTestContentUrl); + navigation_simulator()->Start(); + navigation_simulator()->SetContentsMimeType("multipart/related"); + navigation_simulator()->Commit(); + + ASSERT_NE(nullptr, tab_helper()->offline_page()); + EXPECT_FALSE(tab_helper()->IsShowingTrustedOfflinePage()); + EXPECT_EQ(OfflinePageHeader::Reason::NONE, + tab_helper()->offline_header().reason); +} +#endif + } // namespace offline_pages
diff --git a/chrome/browser/offline_pages/offline_page_utils.cc b/chrome/browser/offline_pages/offline_page_utils.cc index d06a896..f7fae7ea 100644 --- a/chrome/browser/offline_pages/offline_page_utils.cc +++ b/chrome/browser/offline_pages/offline_page_utils.cc
@@ -177,17 +177,21 @@ const OfflinePageItem* offline_page = tab_helper->offline_page(); if (!offline_page) return nullptr; + // TODO(jianli): Remove this when the UI knows how to handle untrusted + // offline pages. + if (!tab_helper->IsShowingTrustedOfflinePage()) + return nullptr; - // Returns the cached offline page only if the offline URL matches with - // current tab URL (skipping fragment identifier part). This is to prevent + // If a pending navigation that hasn't committed yet, don't return the cached + // offline page that was set at the last commit time. This is to prevent // from returning the wrong offline page if DidStartNavigation is never called // to clear it up. - GURL::Replacements remove_params; - remove_params.ClearRef(); - GURL offline_url = offline_page->url.ReplaceComponents(remove_params); - GURL web_contents_url = - web_contents->GetVisibleURL().ReplaceComponents(remove_params); - return offline_url == web_contents_url ? offline_page : nullptr; + if (!EqualsIgnoringFragment(web_contents->GetVisibleURL(), + web_contents->GetLastCommittedURL())) { + return nullptr; + } + + return offline_page; } // static
diff --git a/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer.h b/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer.h index f73f0a7..5c135be 100644 --- a/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer.h +++ b/chrome/browser/page_load_metrics/observers/data_reduction_proxy_metrics_observer.h
@@ -28,17 +28,6 @@ // Various UMA histogram names for DataReductionProxy core page load metrics. extern const char kHistogramDataReductionProxyPrefix[]; extern const char kHistogramDataReductionProxyLoFiOnPrefix[]; -extern const char kHistogramDOMContentLoadedEventFiredSuffix[]; -extern const char kHistogramFirstLayoutSuffix[]; -extern const char kHistogramLoadEventFiredSuffix[]; -extern const char kHistogramFirstContentfulPaintSuffix[]; -extern const char kHistogramFirstMeaningfulPaintSuffix[]; -extern const char kHistogramFirstImagePaintSuffix[]; -extern const char kHistogramFirstPaintSuffix[]; -extern const char kHistogramFirstTextPaintSuffix[]; -extern const char kHistogramParseStartSuffix[]; -extern const char kHistogramParseBlockedOnScriptLoadSuffix[]; -extern const char kHistogramParseDurationSuffix[]; // Byte and request specific histogram suffixes. extern const char kResourcesPercentProxied[];
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 6a5d91c..9acfb5b6e 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -22,7 +22,6 @@ #include "chrome/browser/external_protocol/external_protocol_handler.h" #include "chrome/browser/first_run/first_run.h" #include "chrome/browser/gpu/gpu_mode_manager.h" -#include "chrome/browser/gpu/gpu_profile_cache.h" #include "chrome/browser/intranet_redirect_detector.h" #include "chrome/browser/io_thread.h" #include "chrome/browser/media/media_device_id_salt.h" @@ -176,6 +175,7 @@ #include "chrome/browser/android/oom_intervention/oom_intervention_decider.h" #include "chrome/browser/android/preferences/browser_prefs_android.h" #include "chrome/browser/geolocation/geolocation_permission_context_android.h" +#include "chrome/browser/gpu/gpu_driver_info_manager_android.h" #include "chrome/browser/ntp_snippets/download_suggestions_provider.h" #include "components/cdm/browser/media_drm_storage_impl.h" #include "components/ntp_snippets/breaking_news/breaking_news_gcm_app_handler.h" @@ -353,7 +353,6 @@ ExternalProtocolHandler::RegisterPrefs(registry); flags_ui::PrefServiceFlagsStorage::RegisterPrefs(registry); GpuModeManager::RegisterPrefs(registry); - GpuProfileCache::RegisterPrefs(registry); IntranetRedirectDetector::RegisterPrefs(registry); IOThread::RegisterPrefs(registry); network_time::NetworkTimeTracker::RegisterPrefs(registry); @@ -388,7 +387,7 @@ #if defined(OS_ANDROID) ::android::RegisterPrefs(registry); - + GpuDriverInfoManager::RegisterPrefs(registry); // Obsolete activity prefs. See MigrateObsoleteBrowserPrefs(). registry->RegisterIntegerPref(kStabilityForegroundActivityType, 0); registry->RegisterIntegerPref(kStabilityLaunchedActivityFlags, 0);
diff --git a/chrome/browser/previews/previews_infobar_tab_helper_unittest.cc b/chrome/browser/previews/previews_infobar_tab_helper_unittest.cc index ef992b3f..cc1b4e92 100644 --- a/chrome/browser/previews/previews_infobar_tab_helper_unittest.cc +++ b/chrome/browser/previews/previews_infobar_tab_helper_unittest.cc
@@ -240,7 +240,7 @@ int64_t expected_file_size = .55 * item.file_size; offline_pages::OfflinePageHeader header; offline_pages::OfflinePageTabHelper::FromWebContents(web_contents()) - ->SetOfflinePage(item, header, true); + ->SetOfflinePage(item, header, true, true); auto* data_reduction_proxy_settings = DataReductionProxyChromeSettingsFactory::GetForBrowserContext(
diff --git a/chrome/browser/printing/cloud_print/privet_http_unittest.cc b/chrome/browser/printing/cloud_print/privet_http_unittest.cc index 49d9804..b1b3a412 100644 --- a/chrome/browser/printing/cloud_print/privet_http_unittest.cc +++ b/chrome/browser/printing/cloud_print/privet_http_unittest.cc
@@ -229,11 +229,28 @@ } })"; +const char kSampleCapabilitiesResponsePWGSettingsMono[] = + R"({ + "version": "1.0", + "printer": { + "pwg_raster_config": { + "document_type_supported": [ "SGRAY_8" ], + "document_sheet_back": "ROTATED" + } + } + })"; + const char kSampleCJTDuplex[] = R"({ "version" : "1.0", "print": { "duplex": {"type": "SHORT_EDGE"} } })"; + +const char kSampleCJTMono[] = + R"({ + "version" : "1.0", + "print": { "color": {"type": "STANDARD_MONOCHROME"} } + })"; #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) const char* const kTestParams[] = {"8.8.4.4", "2001:4860:4860::8888"}; @@ -880,6 +897,9 @@ pwg_converter_->bitmap_settings().odd_page_transform); EXPECT_FALSE(pwg_converter_->bitmap_settings().rotate_all_pages); EXPECT_FALSE(pwg_converter_->bitmap_settings().reverse_page_order); + + // Defaults to true when the color is not specified. + EXPECT_TRUE(pwg_converter_->bitmap_settings().use_color); } TEST_P(PrivetLocalPrintTest, SuccessfulPWGLocalPrintDuplex) { @@ -914,6 +934,83 @@ pwg_converter_->bitmap_settings().odd_page_transform); EXPECT_FALSE(pwg_converter_->bitmap_settings().rotate_all_pages); EXPECT_TRUE(pwg_converter_->bitmap_settings().reverse_page_order); + + // Defaults to true when the color is not specified. + EXPECT_TRUE(pwg_converter_->bitmap_settings().use_color); +} + +TEST_P(PrivetLocalPrintTest, SuccessfulPWGLocalPrintMono) { + local_print_operation_->SetUsername("sample@gmail.com"); + local_print_operation_->SetJobname("Sample job name"); + local_print_operation_->SetData(RefCountedBytesFromString("path/to/")); + local_print_operation_->SetTicket(kSampleCJTMono); + local_print_operation_->SetCapabilities( + kSampleCapabilitiesResponsePWGSettings); + local_print_operation_->Start(); + + EXPECT_TRUE(SuccessfulResponseToURL(GetUrl("/privet/info"), + kSampleInfoResponseWithCreatejob)); + + EXPECT_TRUE( + SuccessfulResponseToURL(GetUrl("/privet/info"), kSampleInfoResponse)); + + EXPECT_TRUE(SuccessfulResponseToURLAndJSONData( + GetUrl("/privet/printer/createjob"), kSampleCJTMono, + kSampleCreatejobResponse)); + + EXPECT_CALL(local_print_delegate_, OnPrivetPrintingDoneInternal()); + + EXPECT_TRUE(SuccessfulResponseToURLAndFilePath( + GetUrl("/privet/printer/submitdoc?" + "client_name=Chrome&user_name=sample%40gmail.com" + "&job_name=Sample+job+name&job_id=1234"), + base::FilePath(FILE_PATH_LITERAL("path/to/test.pdf")), + kSampleLocalPrintResponse)); + + EXPECT_EQ(printing::TRANSFORM_NORMAL, + pwg_converter_->bitmap_settings().odd_page_transform); + EXPECT_FALSE(pwg_converter_->bitmap_settings().rotate_all_pages); + EXPECT_TRUE(pwg_converter_->bitmap_settings().reverse_page_order); + + // Ticket specified mono, but no SGRAY_8 color capability. + EXPECT_TRUE(pwg_converter_->bitmap_settings().use_color); +} + +TEST_P(PrivetLocalPrintTest, SuccessfulPWGLocalPrintMonoToGRAY8Printer) { + local_print_operation_->SetUsername("sample@gmail.com"); + local_print_operation_->SetJobname("Sample job name"); + local_print_operation_->SetData(RefCountedBytesFromString("path/to/")); + local_print_operation_->SetTicket(kSampleCJTMono); + local_print_operation_->SetCapabilities( + kSampleCapabilitiesResponsePWGSettingsMono); + local_print_operation_->Start(); + + EXPECT_TRUE(SuccessfulResponseToURL(GetUrl("/privet/info"), + kSampleInfoResponseWithCreatejob)); + + EXPECT_TRUE( + SuccessfulResponseToURL(GetUrl("/privet/info"), kSampleInfoResponse)); + + EXPECT_TRUE(SuccessfulResponseToURLAndJSONData( + GetUrl("/privet/printer/createjob"), kSampleCJTMono, + kSampleCreatejobResponse)); + + EXPECT_CALL(local_print_delegate_, OnPrivetPrintingDoneInternal()); + + EXPECT_TRUE(SuccessfulResponseToURLAndFilePath( + GetUrl("/privet/printer/submitdoc?" + "client_name=Chrome&user_name=sample%40gmail.com" + "&job_name=Sample+job+name&job_id=1234"), + base::FilePath(FILE_PATH_LITERAL("path/to/test.pdf")), + kSampleLocalPrintResponse)); + + EXPECT_EQ(printing::TRANSFORM_NORMAL, + pwg_converter_->bitmap_settings().odd_page_transform); + EXPECT_FALSE(pwg_converter_->bitmap_settings().rotate_all_pages); + EXPECT_FALSE(pwg_converter_->bitmap_settings().reverse_page_order); + + // Ticket specified mono, and SGRAY_8 color capability exists. + EXPECT_FALSE(pwg_converter_->bitmap_settings().use_color); } TEST_P(PrivetLocalPrintTest, SuccessfulLocalPrintWithCreatejob) {
diff --git a/chrome/browser/printing/pdf_to_emf_converter.cc b/chrome/browser/printing/pdf_to_emf_converter.cc index ee29482..7563626 100644 --- a/chrome/browser/printing/pdf_to_emf_converter.cc +++ b/chrome/browser/printing/pdf_to_emf_converter.cc
@@ -11,6 +11,7 @@ #include <utility> #include <vector> +#include "base/callback.h" #include "base/containers/queue.h" #include "base/files/file.h" #include "base/files/file_util.h" @@ -24,18 +25,16 @@ #include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/thread_restrictions.h" #include "base/threading/thread_task_runner_handle.h" -#include "chrome/common/chrome_utility_printing_messages.h" -#include "chrome/common/printing/pdf_to_emf_converter.mojom.h" -#include "chrome/grit/generated_resources.h" +#include "chrome/services/printing/public/interfaces/constants.mojom.h" +#include "chrome/services/printing/public/interfaces/pdf_to_emf_converter.mojom.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/child_process_data.h" -#include "content/public/browser/utility_process_host.h" -#include "content/public/browser/utility_process_host_client.h" +#include "content/public/common/service_manager_connection.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/system/platform_handle.h" #include "printing/emf_win.h" #include "printing/pdf_render_settings.h" -#include "ui/base/l10n/l10n_util.h" +#include "services/service_manager/public/cpp/connector.h" using content::BrowserThread; @@ -43,8 +42,6 @@ namespace { -class PdfConverterImpl; - void CloseFileOnBlockingTaskRunner(base::File temp_file) { base::AssertBlockingAllowed(); temp_file.Close(); @@ -194,36 +191,25 @@ }; // Class for converting PDF to another format for printing (Emf, Postscript). -// Class uses UI thread, IO thread and |blocking_task_runner_|. +// Class uses UI thread and |blocking_task_runner_|. // Internal workflow is following: // 1. Create instance on the UI thread. (files_, settings_,) // 2. Create pdf file on |blocking_task_runner_|. -// 3. Start utility process and start conversion on the IO thread. -// 4. Utility process returns page count. +// 3. Bind to printing service and start conversion on the UI thread (mojo +// actually makes that happen transparently on the IO thread). +// 4. Printing service returns page count. // 5. For each page: // 1. Clients requests page with file handle to a temp file. // 2. Utility converts the page, save it to the file and reply. // // All these steps work sequentially, so no data should be accessed // simultaneously by several threads. -class PdfConverterUtilityProcessHostClient - : public content::UtilityProcessHostClient { +class PdfConverterImpl : public PdfConverter { public: - PdfConverterUtilityProcessHostClient( - base::WeakPtr<PdfConverterImpl> converter, - const PdfRenderSettings& settings); - - void Start(const scoped_refptr<base::RefCountedMemory>& data, - PdfConverter::StartCallback start_callback); - - void GetPage(int page_number, - const PdfConverter::GetPageCallback& get_page_callback); - - void Stop(); - - // UtilityProcessHostClient implementation. - void OnProcessCrashed(int exit_code) override; - void OnProcessLaunchFailed(int exit_code) override; + PdfConverterImpl(const scoped_refptr<base::RefCountedMemory>& data, + const PdfRenderSettings& conversion_settings, + StartCallback start_callback); + ~PdfConverterImpl() override; private: class GetPageCallbackData { @@ -243,8 +229,11 @@ } int page_number() const { return page_number_; } + const PdfConverter::GetPageCallback& callback() const { return callback_; } + ScopedTempFile TakeFile() { return std::move(file_); } + void set_file(ScopedTempFile file) { file_ = std::move(file); } private: @@ -256,20 +245,16 @@ DISALLOW_COPY_AND_ASSIGN(GetPageCallbackData); }; - ~PdfConverterUtilityProcessHostClient() override; + void GetPage(int page_number, + const PdfConverter::GetPageCallback& get_page_callback) override; - bool OnMessageReceived(const IPC::Message& message) override; + void Stop(); // Helper functions: must be overridden by subclasses - // Set the process name - base::string16 GetName() const; // Create a metafileplayer subclass file from a temporary file. std::unique_ptr<MetafilePlayer> GetFileFromTemp(ScopedTempFile temp_file); - // Message handlers: - void OnPageCount(mojom::PdfToEmfConverterFactoryPtr factory_keep_alive, - mojom::PdfToEmfConverterPtr converter, - uint32_t page_count); + void OnPageCount(mojom::PdfToEmfConverterPtr converter, uint32_t page_count); void OnPageDone(bool success, float scale_factor); void OnFailed(const std::string& error_message); @@ -283,16 +268,11 @@ scoped_refptr<RefCountedTempDir> temp_dir_; - // Used to suppress callbacks after PdfConverter is deleted. - base::WeakPtr<PdfConverterImpl> converter_; PdfRenderSettings settings_; // Document loaded callback. PdfConverter::StartCallback start_callback_; - // Process host for IPC. - base::WeakPtr<content::UtilityProcessHost> utility_process_host_; - // Queue of callbacks for GetPage() requests. Utility process should reply // with PageDone in the same order as requests were received. // Use containers that keeps element pointers valid after push() and pop(). @@ -306,54 +286,24 @@ mojom::PdfToEmfConverterPtr pdf_to_emf_converter_; - DISALLOW_COPY_AND_ASSIGN(PdfConverterUtilityProcessHostClient); -}; - -std::unique_ptr<MetafilePlayer> -PdfConverterUtilityProcessHostClient::GetFileFromTemp( - ScopedTempFile temp_file) { - if (settings_.mode == PdfRenderSettings::Mode::POSTSCRIPT_LEVEL2 || - settings_.mode == PdfRenderSettings::Mode::POSTSCRIPT_LEVEL3 || - settings_.mode == PdfRenderSettings::Mode::TEXTONLY) { - return base::MakeUnique<PostScriptMetaFile>(temp_dir_, - std::move(temp_file)); - } - return base::MakeUnique<LazyEmf>(temp_dir_, std::move(temp_file)); -} - -class PdfConverterImpl : public PdfConverter { - public: - PdfConverterImpl(); - - ~PdfConverterImpl() override; - - base::WeakPtr<PdfConverterImpl> GetWeakPtr() { - return weak_ptr_factory_.GetWeakPtr(); - } - - void Start(const scoped_refptr<base::RefCountedMemory>& data, - const PdfRenderSettings& conversion_settings, - StartCallback start_callback); - - void GetPage(int page_number, - const GetPageCallback& get_page_callback) override; - - // Helps to cancel callbacks if this object is destroyed. - void RunCallback(base::OnceClosure callback); - - void Start( - const scoped_refptr<PdfConverterUtilityProcessHostClient>& utility_client, - const scoped_refptr<base::RefCountedMemory>& data, - StartCallback start_callback); - - private: - scoped_refptr<PdfConverterUtilityProcessHostClient> utility_client_; + mojom::PdfToEmfConverterFactoryPtr pdf_to_emf_converter_factory_; base::WeakPtrFactory<PdfConverterImpl> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(PdfConverterImpl); }; +std::unique_ptr<MetafilePlayer> PdfConverterImpl::GetFileFromTemp( + ScopedTempFile temp_file) { + if (settings_.mode == PdfRenderSettings::Mode::POSTSCRIPT_LEVEL2 || + settings_.mode == PdfRenderSettings::Mode::POSTSCRIPT_LEVEL3 || + settings_.mode == PdfRenderSettings::Mode::TEXTONLY) { + return std::make_unique<PostScriptMetaFile>(temp_dir_, + std::move(temp_file)); + } + return std::make_unique<LazyEmf>(temp_dir_, std::move(temp_file)); +} + ScopedTempFile CreateTempFile(scoped_refptr<RefCountedTempDir>* temp_dir) { if (!temp_dir->get()) *temp_dir = base::MakeRefCounted<RefCountedTempDir>(); @@ -366,7 +316,7 @@ << (*temp_dir)->GetPath().value(); return file; } - file = base::MakeUnique<TempFile>(base::File( + file = std::make_unique<TempFile>(base::File( path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE | base::File::FLAG_READ | base::File::FLAG_DELETE_ON_CLOSE | base::File::FLAG_TEMPORARY)); @@ -462,59 +412,39 @@ return true; } -PdfConverterUtilityProcessHostClient::PdfConverterUtilityProcessHostClient( - base::WeakPtr<PdfConverterImpl> converter, - const PdfRenderSettings& settings) - : converter_(converter), - settings_(settings), +PdfConverterImpl::PdfConverterImpl( + const scoped_refptr<base::RefCountedMemory>& data, + const PdfRenderSettings& settings, + StartCallback start_callback) + : settings_(settings), + start_callback_(std::move(start_callback)), blocking_task_runner_(base::CreateSequencedTaskRunnerWithTraits( {base::MayBlock(), base::TaskPriority::USER_VISIBLE, - base::TaskShutdownBehavior::BLOCK_SHUTDOWN})) {} - -PdfConverterUtilityProcessHostClient::~PdfConverterUtilityProcessHostClient() {} - -void PdfConverterUtilityProcessHostClient::Start( - const scoped_refptr<base::RefCountedMemory>& data, - PdfConverter::StartCallback start_callback) { - if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&PdfConverterUtilityProcessHostClient::Start, this, data, - std::move(start_callback))); - return; - } - - // Store callback before any OnFailed() call to make it called on failure. - DCHECK(start_callback); - start_callback_ = std::move(start_callback); - - // NOTE: This process _must_ be sandboxed, otherwise the pdf dll will load - // gdiplus.dll, change how rendering happens, and not be able to correctly - // generate when sent to a metafile DC. - utility_process_host_ = content::UtilityProcessHost::Create( - this, base::ThreadTaskRunnerHandle::Get()) - ->AsWeakPtr(); - utility_process_host_->SetName(GetName()); - utility_process_host_->Start(); + base::TaskShutdownBehavior::BLOCK_SHUTDOWN})), + weak_ptr_factory_(this) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(start_callback_); base::PostTaskAndReplyWithResult( blocking_task_runner_.get(), FROM_HERE, - base::Bind(&CreateTempPdfFile, data, &temp_dir_), - base::Bind(&PdfConverterUtilityProcessHostClient::OnTempPdfReady, this)); + base::BindOnce(&CreateTempPdfFile, data, &temp_dir_), + base::BindOnce(&PdfConverterImpl::OnTempPdfReady, + weak_ptr_factory_.GetWeakPtr())); } -void PdfConverterUtilityProcessHostClient::OnTempPdfReady(ScopedTempFile pdf) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (!utility_process_host_ || !pdf) +PdfConverterImpl::~PdfConverterImpl() {} + +void PdfConverterImpl::OnTempPdfReady(ScopedTempFile pdf) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (!pdf) return OnFailed(std::string("Failed to create temporary PDF file.")); - mojom::PdfToEmfConverterFactoryPtr pdf_to_emf_converter_factory_ptr; - utility_process_host_->BindInterface( - mojom::PdfToEmfConverterFactory::Name_, - mojo::MakeRequest(&pdf_to_emf_converter_factory_ptr).PassMessagePipe()); - - pdf_to_emf_converter_factory_ptr.set_connection_error_handler(base::BindOnce( - &PdfConverterUtilityProcessHostClient::OnFailed, this, + content::ServiceManagerConnection::GetForProcess() + ->GetConnector() + ->BindInterface(printing::mojom::kChromePrintingServiceName, + &pdf_to_emf_converter_factory_); + pdf_to_emf_converter_factory_.set_connection_error_handler(base::BindOnce( + &PdfConverterImpl::OnFailed, weak_ptr_factory_.GetWeakPtr(), std::string("Connection to PdfToEmfConverterFactory error."))); mojom::PdfToEmfConverterClientPtr pdf_to_emf_converter_client_ptr; @@ -522,59 +452,49 @@ std::make_unique<PdfToEmfConverterClientImpl>( mojo::MakeRequest(&pdf_to_emf_converter_client_ptr)); - pdf_to_emf_converter_factory_ptr->CreateConverter( + pdf_to_emf_converter_factory_->CreateConverter( mojo::WrapPlatformFile(pdf->file().TakePlatformFile()), settings_, std::move(pdf_to_emf_converter_client_ptr), - base::BindOnce(&PdfConverterUtilityProcessHostClient::OnPageCount, this, - std::move(pdf_to_emf_converter_factory_ptr))); + base::BindOnce(&PdfConverterImpl::OnPageCount, + weak_ptr_factory_.GetWeakPtr())); } -void PdfConverterUtilityProcessHostClient::OnPageCount( - mojom::PdfToEmfConverterFactoryPtr factory_keep_alive, - mojom::PdfToEmfConverterPtr converter, - uint32_t page_count) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); +void PdfConverterImpl::OnPageCount(mojom::PdfToEmfConverterPtr converter, + uint32_t page_count) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!pdf_to_emf_converter_.is_bound()); pdf_to_emf_converter_ = std::move(converter); - - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::BindOnce(&PdfConverterImpl::RunCallback, converter_, - base::BindOnce(std::move(start_callback_), page_count))); + pdf_to_emf_converter_.set_connection_error_handler(base::BindOnce( + &PdfConverterImpl::OnFailed, weak_ptr_factory_.GetWeakPtr(), + std::string("Connection to PdfToEmfConverter error."))); + std::move(start_callback_).Run(page_count); } -void PdfConverterUtilityProcessHostClient::GetPage( +void PdfConverterImpl::GetPage( int page_number, const PdfConverter::GetPageCallback& get_page_callback) { - if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::BindOnce(&PdfConverterUtilityProcessHostClient::GetPage, this, - page_number, get_page_callback)); - return; - } - + DCHECK_CURRENTLY_ON(BrowserThread::UI); // Store callback before any OnFailed() call to make it called on failure. get_page_callbacks_.push(GetPageCallbackData(page_number, get_page_callback)); - if (!utility_process_host_) - return OnFailed(std::string("No process utility host.")); + if (!pdf_to_emf_converter_) + return OnFailed(std::string("No PdfToEmfConverter.")); base::PostTaskAndReplyWithResult( blocking_task_runner_.get(), FROM_HERE, - base::Bind(&CreateTempFile, &temp_dir_), - base::Bind(&PdfConverterUtilityProcessHostClient::OnTempFileReady, this, - &get_page_callbacks_.back())); + base::BindOnce(&CreateTempFile, &temp_dir_), + base::BindOnce(&PdfConverterImpl::OnTempFileReady, + weak_ptr_factory_.GetWeakPtr(), + &get_page_callbacks_.back())); } -void PdfConverterUtilityProcessHostClient::OnTempFileReady( - GetPageCallbackData* callback_data, - ScopedTempFile temp_file) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); +void PdfConverterImpl::OnTempFileReady(GetPageCallbackData* callback_data, + ScopedTempFile temp_file) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(pdf_to_emf_converter_.is_bound()); - if (!utility_process_host_ || !temp_file) - return OnFailed(std::string("Error creating utility process host")); + if (!pdf_to_emf_converter_ || !temp_file) + return OnFailed(std::string("Error connecting to printing service.")); // We need to dup the file as mojo::WrapPlatformFile takes ownership of the // passed file. @@ -582,13 +502,13 @@ pdf_to_emf_converter_->ConvertPage( callback_data->page_number(), mojo::WrapPlatformFile(temp_file_copy.TakePlatformFile()), - base::BindOnce(&PdfConverterUtilityProcessHostClient::OnPageDone, this)); + base::BindOnce(&PdfConverterImpl::OnPageDone, + weak_ptr_factory_.GetWeakPtr())); callback_data->set_file(std::move(temp_file)); } -void PdfConverterUtilityProcessHostClient::OnPageDone(bool success, - float scale_factor) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); +void PdfConverterImpl::OnPageDone(bool success, float scale_factor) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (get_page_callbacks_.empty()) return OnFailed(std::string("No get_page callbacks.")); GetPageCallbackData& data = get_page_callbacks_.front(); @@ -596,62 +516,35 @@ if (success) { ScopedTempFile temp_file = data.TakeFile(); - if (!temp_file) // Unexpected message from utility process. + if (!temp_file) // Unexpected message from printing service. return OnFailed("No temp file."); file = GetFileFromTemp(std::move(temp_file)); } - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&PdfConverterImpl::RunCallback, converter_, - base::BindRepeating(data.callback(), data.page_number(), - scale_factor, base::Passed(&file)))); + data.callback().Run(data.page_number(), scale_factor, std::move(file)); get_page_callbacks_.pop(); } -void PdfConverterUtilityProcessHostClient::Stop() { - if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&PdfConverterUtilityProcessHostClient::Stop, this)); - return; - } +void PdfConverterImpl::Stop() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + // Disconnect interface ptrs so that the printing service process stop. + pdf_to_emf_converter_factory_.reset(); pdf_to_emf_converter_.reset(); - // Once this becomes a Mojo service, simply disconnecting - // pdf_to_emf_converter_ above will lead to the utility process stopping. - // In the meantime we need to explictly terminate it. - if (utility_process_host_) { - utility_process_host_->Send( - new ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop()); - } } -void PdfConverterUtilityProcessHostClient::OnProcessCrashed(int exit_code) { - OnFailed("Utility process host crashed."); -} - -void PdfConverterUtilityProcessHostClient::OnProcessLaunchFailed( - int exit_code) { - OnFailed("Process launch failed"); -} - -void PdfConverterUtilityProcessHostClient::OnFailed( - const std::string& error_message) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); +void PdfConverterImpl::OnFailed(const std::string& error_message) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); LOG(ERROR) << "Failed to convert PDF: " << error_message; if (!start_callback_.is_null()) { - OnPageCount(mojom::PdfToEmfConverterFactoryPtr(), - mojom::PdfToEmfConverterPtr(), 0); + OnPageCount(mojom::PdfToEmfConverterPtr(), 0); } while (!get_page_callbacks_.empty()) OnPageDone(false, 0.0f); - utility_process_host_.reset(); + Stop(); } - -void PdfConverterUtilityProcessHostClient::OnPreCacheFontCharacters( - const LOGFONT& font, - const base::string16& str) { +void PdfConverterImpl::OnPreCacheFontCharacters(const LOGFONT& font, + const base::string16& str) { // TODO(scottmg): pdf/ppapi still require the renderer to be able to precache // GDI fonts (http://crbug.com/383227), even when using DirectWrite. // Eventually this shouldn't be added and should be moved to @@ -681,57 +574,17 @@ DeleteEnhMetaFile(metafile); } -bool PdfConverterUtilityProcessHostClient::OnMessageReceived( - const IPC::Message& message) { - return false; -} - -base::string16 PdfConverterUtilityProcessHostClient::GetName() const { - return l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_PDF_CONVERTOR_NAME); -} - -// Pdf Converter Impl and subclasses -PdfConverterImpl::PdfConverterImpl() : weak_ptr_factory_(this) {} - -PdfConverterImpl::~PdfConverterImpl() { - if (utility_client_.get()) - utility_client_->Stop(); -} - -void PdfConverterImpl::Start( - const scoped_refptr<PdfConverterUtilityProcessHostClient>& utility_client, - const scoped_refptr<base::RefCountedMemory>& data, - StartCallback start_callback) { - DCHECK(!utility_client_); - utility_client_ = utility_client; - utility_client_->Start(data, std::move(start_callback)); -} - -void PdfConverterImpl::GetPage(int page_number, - const GetPageCallback& get_page_callback) { - utility_client_->GetPage(page_number, get_page_callback); -} - -void PdfConverterImpl::RunCallback(base::OnceClosure callback) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - std::move(callback).Run(); -} - } // namespace -PdfConverter::~PdfConverter() {} +PdfConverter::~PdfConverter() = default; // static std::unique_ptr<PdfConverter> PdfConverter::StartPdfConverter( const scoped_refptr<base::RefCountedMemory>& data, const PdfRenderSettings& conversion_settings, StartCallback start_callback) { - std::unique_ptr<PdfConverterImpl> converter = - base::MakeUnique<PdfConverterImpl>(); - converter->Start(new PdfConverterUtilityProcessHostClient( - converter->GetWeakPtr(), conversion_settings), - data, std::move(start_callback)); - return std::move(converter); + return std::make_unique<PdfConverterImpl>(data, conversion_settings, + std::move(start_callback)); } } // namespace printing
diff --git a/chrome/browser/printing/pdf_to_emf_converter.h b/chrome/browser/printing/pdf_to_emf_converter.h index 6fa4c235..1263c44 100644 --- a/chrome/browser/printing/pdf_to_emf_converter.h +++ b/chrome/browser/printing/pdf_to_emf_converter.h
@@ -7,7 +7,7 @@ #include <memory> -#include "base/callback.h" +#include "base/callback_forward.h" #include "base/memory/ref_counted_memory.h" namespace printing {
diff --git a/chrome/browser/printing/print_job.cc b/chrome/browser/printing/print_job.cc index 67f7427..5f268557 100644 --- a/chrome/browser/printing/print_job.cc +++ b/chrome/browser/printing/print_job.cc
@@ -275,7 +275,7 @@ print_text_with_gdi ? PdfRenderSettings::Mode::GDI_TEXT : PdfRenderSettings::Mode::NORMAL); pdf_conversion_state_->Start( - bytes, settings, base::Bind(&PrintJob::OnPdfConversionStarted, this)); + bytes, settings, base::BindOnce(&PrintJob::OnPdfConversionStarted, this)); } void PrintJob::OnPdfConversionStarted(int page_count) { @@ -321,7 +321,7 @@ /*autorotate=*/true, PdfRenderSettings::Mode::TEXTONLY); pdf_conversion_state_->Start( - bytes, settings, base::Bind(&PrintJob::OnPdfConversionStarted, this)); + bytes, settings, base::BindOnce(&PrintJob::OnPdfConversionStarted, this)); } void PrintJob::StartPdfToPostScriptConversion( @@ -338,7 +338,7 @@ ps_level2 ? PdfRenderSettings::Mode::POSTSCRIPT_LEVEL2 : PdfRenderSettings::Mode::POSTSCRIPT_LEVEL3); pdf_conversion_state_->Start( - bytes, settings, base::Bind(&PrintJob::OnPdfConversionStarted, this)); + bytes, settings, base::BindOnce(&PrintJob::OnPdfConversionStarted, this)); } #endif // defined(OS_WIN)
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc index a3598d8..9277cc2 100644 --- a/chrome/browser/printing/print_view_manager_base.cc +++ b/chrome/browser/printing/print_view_manager_base.cc
@@ -16,6 +16,7 @@ #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/strings/utf_string_conversions.h" +#include "base/task_scheduler/post_task.h" #include "base/threading/thread_task_runner_handle.h" #include "base/timer/timer.h" #include "build/build_config.h" @@ -26,6 +27,7 @@ #include "chrome/browser/printing/printer_query.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/simple_message_box.h" +#include "chrome/browser/ui/webui/print_preview/printer_handler.h" #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" #include "components/prefs/pref_service.h" @@ -38,6 +40,7 @@ #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/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" #include "mojo/public/cpp/system/buffer.h" @@ -107,6 +110,126 @@ } #endif +#if BUILDFLAG(ENABLE_PRINT_PREVIEW) +void PrintViewManagerBase::PrintForPrintPreview( + std::unique_ptr<base::DictionaryValue> job_settings, + const scoped_refptr<base::RefCountedBytes>& print_data, + content::RenderFrameHost* rfh, + PrinterHandler::PrintCallback callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + int page_count; + job_settings->GetInteger(kSettingPreviewPageCount, &page_count); + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::BindOnce(&PrintViewManagerBase::CreateQueryWithSettings, + base::Unretained(this), std::move(job_settings), rfh, + base::BindOnce(&PrintViewManagerBase::OnPrintSettingsDone, + base::Unretained(this), print_data, + page_count, std::move(callback)))); +} + +void PrintViewManagerBase::CreateQueryWithSettings( + std::unique_ptr<base::DictionaryValue> job_settings, + content::RenderFrameHost* rfh, + base::OnceCallback<void(scoped_refptr<printing::PrinterQuery>)> callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + scoped_refptr<printing::PrinterQuery> printer_query = + queue_->CreatePrinterQuery(rfh->GetProcess()->GetID(), + rfh->GetRoutingID()); + printer_query->SetSettings( + std::move(job_settings), + base::BindOnce(std::move(callback), printer_query)); +} +#endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) + +bool PrintViewManagerBase::PrintDocument( + PrintedDocument* document, + const scoped_refptr<base::RefCountedBytes>& print_data, + const gfx::Size& page_size, + const gfx::Rect& content_area, + const gfx::Point& offsets) { + std::unique_ptr<PdfMetafileSkia> metafile = + std::make_unique<PdfMetafileSkia>(SkiaDocumentType::PDF); + if (!metafile->InitFromData(print_data->front(), print_data->size())) { + NOTREACHED() << "Invalid metafile"; + web_contents()->Stop(); + return false; + } + +#if defined(OS_WIN) + if (PrintedDocument::HasDebugDumpPath()) + document->DebugDumpData(print_data.get(), FILE_PATH_LITERAL(".pdf")); + + const auto& settings = document->settings(); + if (settings.printer_is_textonly()) { + print_job_->StartPdfToTextConversion(print_data, page_size); + } else if ((settings.printer_is_ps2() || settings.printer_is_ps3()) && + !base::FeatureList::IsEnabled( + features::kDisablePostScriptPrinting)) { + print_job_->StartPdfToPostScriptConversion( + print_data, content_area, offsets, settings.printer_is_ps2()); + } else { + // TODO(thestig): Figure out why rendering text with GDI results in random + // missing characters for some users. https://crbug.com/658606 + // Update : The missing letters seem to have been caused by the same + // problem as https://crbug.com/659604 which was resolved. GDI printing + // seems to work with the fix for this bug applied. + bool print_text_with_gdi = + settings.print_text_with_gdi() && !settings.printer_is_xps() && + base::FeatureList::IsEnabled(features::kGdiTextPrinting); + print_job_->StartPdfToEmfConversion(print_data, page_size, content_area, + print_text_with_gdi); + } +#else + // Update the rendered document. It will send notifications to the listener. + document->SetDocument(std::move(metafile), page_size, content_area); + ShouldQuitFromInnerMessageLoop(); +#endif + return true; +} + +#if BUILDFLAG(ENABLE_PRINT_PREVIEW) +void PrintViewManagerBase::OnPrintSettingsDone( + const scoped_refptr<base::RefCountedBytes>& print_data, + int page_count, + PrinterHandler::PrintCallback callback, + scoped_refptr<printing::PrinterQuery> printer_query) { + queue_->QueuePrinterQuery(printer_query.get()); + + // Post task so that the query has time to reset the callback before calling + // OnDidGetPrintedPagesCount. + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::BindOnce(&PrintViewManagerBase::StartLocalPrintJob, + base::Unretained(this), print_data, page_count, + printer_query, std::move(callback))); +} + +void PrintViewManagerBase::StartLocalPrintJob( + const scoped_refptr<base::RefCountedBytes>& print_data, + int page_count, + scoped_refptr<printing::PrinterQuery> printer_query, + PrinterHandler::PrintCallback callback) { + const printing::PrintSettings& settings = printer_query->settings(); + OnDidGetPrintedPagesCount(printer_query->cookie(), page_count); + + gfx::Size page_size = settings.page_setup_device_units().physical_size(); + gfx::Rect content_area = + gfx::Rect(0, 0, page_size.width(), page_size.height()); + gfx::Point offsets = + gfx::Point(settings.page_setup_device_units().content_area().x(), + settings.page_setup_device_units().content_area().y()); + // Print + PrintedDocument* document = GetDocument(printer_query->cookie()); + if (!document || + !PrintDocument(document, print_data, page_size, content_area, offsets)) { + std::move(callback).Run(base::Value("Failed to print")); + } else { + std::move(callback).Run(base::Value()); + } +} +#endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) + void PrintViewManagerBase::UpdatePrintingEnabled() { web_contents()->ForEachFrame( base::Bind(&PrintViewManagerBase::SendPrintingEnabled, @@ -131,6 +254,19 @@ OpportunisticallyCreatePrintJob(cookie); } +PrintedDocument* PrintViewManagerBase::GetDocument(int cookie) { + if (!OpportunisticallyCreatePrintJob(cookie)) + return nullptr; + + PrintedDocument* document = print_job_->document(); + if (!document || cookie != document->cookie()) { + // Out of sync. It may happen since we are completely asynchronous. Old + // spurious messages can be received if one of the processes is overloaded. + return nullptr; + } + return document; +} + void PrintViewManagerBase::OnComposePdfDone( const PrintHostMsg_DidPrintDocument_Params& params, mojom::PdfCompositor::Status status, @@ -141,22 +277,26 @@ return; } - UpdateForPrintedDocument(params, GetShmFromMojoHandle(std::move(handle))); + PrintedDocument* document = print_job_->document(); + if (!document) + return; + + std::unique_ptr<base::SharedMemory> shared_buf = + GetShmFromMojoHandle(std::move(handle)); + scoped_refptr<base::RefCountedBytes> bytes = + base::MakeRefCounted<base::RefCountedBytes>( + reinterpret_cast<const unsigned char*>(shared_buf->memory()), + shared_buf->mapped_size()); + PrintDocument(document, bytes, params.page_size, params.content_area, + params.physical_offsets); } void PrintViewManagerBase::OnDidPrintDocument( const PrintHostMsg_DidPrintDocument_Params& params) { - // Ready to composite. Starting a print job. - if (!OpportunisticallyCreatePrintJob(params.document_cookie)) + PrintedDocument* document = GetDocument(params.document_cookie); + if (!document) return; - PrintedDocument* document = print_job_->document(); - if (!document || params.document_cookie != document->cookie()) { - // Out of sync. It may happen since we are completely asynchronous. Old - // spurious messages can be received if one of the processes is overloaded. - return; - } - if (!base::SharedMemory::IsHandleValid(params.metafile_data_handle)) { NOTREACHED() << "invalid memory handle"; web_contents()->Stop(); @@ -179,63 +319,12 @@ web_contents()->Stop(); return; } - - UpdateForPrintedDocument(params, std::move(shared_buf)); -} - -void PrintViewManagerBase::UpdateForPrintedDocument( - const PrintHostMsg_DidPrintDocument_Params& params, - std::unique_ptr<base::SharedMemory> shared_buf) { - PrintedDocument* document = print_job_->document(); - if (!document) - return; - -#if defined(OS_WIN) scoped_refptr<base::RefCountedBytes> bytes = base::MakeRefCounted<base::RefCountedBytes>( reinterpret_cast<const unsigned char*>(shared_buf->memory()), - shared_buf->mapped_size()); - - if (PrintedDocument::HasDebugDumpPath()) - document->DebugDumpData(bytes.get(), FILE_PATH_LITERAL(".pdf")); - - const auto& settings = document->settings(); - if (settings.printer_is_textonly()) { - print_job_->StartPdfToTextConversion(bytes, params.page_size); - } else if ((settings.printer_is_ps2() || settings.printer_is_ps3()) && - !base::FeatureList::IsEnabled( - features::kDisablePostScriptPrinting)) { - print_job_->StartPdfToPostScriptConversion(bytes, params.content_area, - params.physical_offsets, - settings.printer_is_ps2()); - } else { - // TODO(thestig): Figure out why rendering text with GDI results in random - // missing characters for some users. https://crbug.com/658606 - // Update : The missing letters seem to have been caused by the same - // problem as https://crbug.com/659604 which was resolved. GDI printing - // seems to work with the fix for this bug applied. - bool print_text_with_gdi = - settings.print_text_with_gdi() && !settings.printer_is_xps() && - base::FeatureList::IsEnabled(features::kGdiTextPrinting); - print_job_->StartPdfToEmfConversion( - bytes, params.page_size, params.content_area, print_text_with_gdi); - } -#else - std::unique_ptr<PdfMetafileSkia> metafile = - std::make_unique<PdfMetafileSkia>(SkiaDocumentType::PDF); - if (!metafile->InitFromData(shared_buf->memory(), - shared_buf->mapped_size())) { - NOTREACHED() << "Invalid metafile header"; - web_contents()->Stop(); - return; - } - - // Update the rendered document. It will send notifications to the listener. - document->SetDocument(std::move(metafile), params.page_size, - params.content_area); - - ShouldQuitFromInnerMessageLoop(); -#endif + params.data_size); + PrintDocument(document, bytes, params.page_size, params.content_area, + params.physical_offsets); } void PrintViewManagerBase::OnPrintingFailed(int cookie) {
diff --git a/chrome/browser/printing/print_view_manager_base.h b/chrome/browser/printing/print_view_manager_base.h index 870e87f..ed76698 100644 --- a/chrome/browser/printing/print_view_manager_base.h +++ b/chrome/browser/printing/print_view_manager_base.h
@@ -12,6 +12,7 @@ #include "base/memory/weak_ptr.h" #include "base/strings/string16.h" #include "build/build_config.h" +#include "chrome/browser/ui/webui/print_preview/printer_handler.h" #include "components/prefs/pref_member.h" #include "components/printing/browser/print_manager.h" #include "components/printing/service/public/interfaces/pdf_compositor.mojom.h" @@ -23,7 +24,7 @@ struct PrintHostMsg_DidPrintDocument_Params; namespace base { -class SharedMemory; +class RefCountedBytes; } namespace content { @@ -36,6 +37,8 @@ class PrintJob; class PrintJobWorkerOwner; class PrintQueriesQueue; +class PrintedDocument; +class PrinterQuery; // Base class for managing the print commands for a WebContents. class PrintViewManagerBase : public content::NotificationObserver, @@ -50,6 +53,18 @@ virtual bool PrintNow(content::RenderFrameHost* rfh); #endif // ENABLE_BASIC_PRINTING +#if BUILDFLAG(ENABLE_PRINT_PREVIEW) + // Prints the document in |print_data| with settings specified in + // |job_settings|. Runs |callback| with an error string on failure and with an + // empty string if the print job is started successfully. |rfh| is the render + // frame host for the preview initiator contents respectively. + void PrintForPrintPreview( + std::unique_ptr<base::DictionaryValue> job_settings, + const scoped_refptr<base::RefCountedBytes>& print_data, + content::RenderFrameHost* rfh, + PrinterHandler::PrintCallback callback); +#endif + // Whether printing is enabled or not. void UpdatePrintingEnabled(); @@ -93,16 +108,31 @@ void OnShowInvalidPrinterSettingsError(); void OnDidPrintDocument(const PrintHostMsg_DidPrintDocument_Params& params); - // Handle extra tasks once the document is printed. - void UpdateForPrintedDocument( - const PrintHostMsg_DidPrintDocument_Params& params, - std::unique_ptr<base::SharedMemory> shared_buf); - // IPC message handlers for service. void OnComposePdfDone(const PrintHostMsg_DidPrintDocument_Params& params, mojom::PdfCompositor::Status status, mojo::ScopedSharedBufferHandle handle); +// Helpers for PrintForPrintPreview(); +#if BUILDFLAG(ENABLE_PRINT_PREVIEW) + void CreateQueryWithSettings( + std::unique_ptr<base::DictionaryValue> job_settings, + content::RenderFrameHost* rfh, + base::OnceCallback<void(scoped_refptr<printing::PrinterQuery>)> callback); + + void OnPrintSettingsDone( + const scoped_refptr<base::RefCountedBytes>& print_data, + int page_count, + PrinterHandler::PrintCallback callback, + scoped_refptr<printing::PrinterQuery> printer_query); + + void StartLocalPrintJob( + const scoped_refptr<base::RefCountedBytes>& print_data, + int page_count, + scoped_refptr<printing::PrinterQuery> printer_query, + PrinterHandler::PrintCallback callback); +#endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) + // Processes a NOTIFY_PRINT_JOB_EVENT notification. void OnNotifyPrintJobEvent(const JobEventDetails& event_details); @@ -111,6 +141,19 @@ // been requested to the renderer. bool RenderAllMissingPagesNow(); + // Checks that synchronization is correct and a print query exists for + // |cookie|. If so, returns the document associated with the cookie. + PrintedDocument* GetDocument(int cookie); + + // Starts printing a document with data given in |print_data|. |print_data| + // must successfully initialize a metafile. |document| is the printed + // document associated with the print job. Returns true if successful. + bool PrintDocument(PrintedDocument* document, + const scoped_refptr<base::RefCountedBytes>& print_data, + const gfx::Size& page_size, + const gfx::Rect& content_area, + const gfx::Point& offsets); + // Quits the current message loop if these conditions hold true: a document is // loaded and is complete and waiting_for_pages_to_be_rendered_ is true. This // function is called in DidPrintDocument() or on ALL_PAGES_REQUESTED
diff --git a/chrome/browser/printing/printing_message_filter.cc b/chrome/browser/printing/printing_message_filter.cc index ad72c5f..ce93911b 100644 --- a/chrome/browser/printing/printing_message_filter.cc +++ b/chrome/browser/printing/printing_message_filter.cc
@@ -307,14 +307,8 @@ } printer_query = queue_->PopPrinterQuery(document_cookie); if (!printer_query.get()) { - int host_id; - int routing_id; - if (!new_settings->GetInteger(kPreviewInitiatorHostId, &host_id) || - !new_settings->GetInteger(kPreviewInitiatorRoutingId, &routing_id)) { - host_id = content::ChildProcessHost::kInvalidUniqueID; - routing_id = MSG_ROUTING_NONE; - } - printer_query = queue_->CreatePrinterQuery(host_id, routing_id); + printer_query = queue_->CreatePrinterQuery( + content::ChildProcessHost::kInvalidUniqueID, MSG_ROUTING_NONE); } printer_query->SetSettings( std::move(new_settings),
diff --git a/chrome/browser/printing/pwg_raster_converter.cc b/chrome/browser/printing/pwg_raster_converter.cc index 4fb3d81..14f13af 100644 --- a/chrome/browser/printing/pwg_raster_converter.cc +++ b/chrome/browser/printing/pwg_raster_converter.cc
@@ -278,6 +278,36 @@ if (duplex_item.LoadFrom(ticket)) duplex_value = duplex_item.value(); + // This assumes |ticket| contains a color ticket item. In case it does not, or + // the color is invalid, |color_value| will default to AUTO_COLOR, which works + // just fine. With AUTO_COLOR, it may be possible to better determine the + // value for |use_color| based on |printer_capabilities|, rather than just + // defaulting to the safe value of true. Parsing |printer_capabilities| + // requires work, which this method is avoiding on purpose. + cloud_devices::printer::Color color_value; + cloud_devices::printer::ColorTicketItem color_item; + if (color_item.LoadFrom(ticket) && color_item.IsValid()) + color_value = color_item.value(); + DCHECK(color_value.IsValid()); + bool use_color; + switch (color_value.type) { + case cloud_devices::printer::STANDARD_MONOCHROME: + case cloud_devices::printer::CUSTOM_MONOCHROME: + use_color = false; + break; + + case cloud_devices::printer::STANDARD_COLOR: + case cloud_devices::printer::CUSTOM_COLOR: + case cloud_devices::printer::AUTO_COLOR: + use_color = true; + break; + + default: + NOTREACHED(); + use_color = true; // Still need to initialize |color| or MSVC will warn. + break; + } + cloud_devices::printer::PwgRasterConfigCapability raster_capability; // If the raster capability fails to load, |raster_capability| will contain // the default value. @@ -306,6 +336,14 @@ result.rotate_all_pages = raster_capability.value().rotate_all_pages; result.reverse_page_order = raster_capability.value().reverse_order_streaming; + + // No need to check for SRGB_8 support in |types|. CDD spec says: + // "any printer that doesn't support SGRAY_8 must be able to perform + // conversion from RGB to grayscale... " + const auto& types = raster_capability.value().document_types_supported; + result.use_color = + use_color || !base::ContainsValue(types, cloud_devices::printer::SGRAY_8); + return result; }
diff --git a/chrome/browser/printing/pwg_raster_converter_browsertest.cc b/chrome/browser/printing/pwg_raster_converter_browsertest.cc index d958240..5532b8e 100644 --- a/chrome/browser/printing/pwg_raster_converter_browsertest.cc +++ b/chrome/browser/printing/pwg_raster_converter_browsertest.cc
@@ -21,6 +21,18 @@ namespace { +// Note that for some reason the generated PWG varies depending on the +// platform (32 or 64 bits) on Linux. +#if defined(OS_LINUX) && defined(ARCH_CPU_32_BITS) +constexpr char kPdfToPwgRasterColorTestFile[] = "pdf_to_pwg_raster_test_32.pwg"; +constexpr char kPdfToPwgRasterMonoTestFile[] = + "pdf_to_pwg_raster_mono_test_32.pwg"; +#else +constexpr char kPdfToPwgRasterColorTestFile[] = "pdf_to_pwg_raster_test.pwg"; +constexpr char kPdfToPwgRasterMonoTestFile[] = + "pdf_to_pwg_raster_mono_test.pwg"; +#endif + void ResultCallbackImpl(bool* called, bool* success_out, base::FilePath* temp_file_out, @@ -33,6 +45,33 @@ quit_closure.Run(); } +void GetPdfData(const char* file_name, + base::FilePath* test_data_dir, + scoped_refptr<base::RefCountedString>* pdf_data) { + ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, test_data_dir)); + *test_data_dir = test_data_dir->AppendASCII("printing"); + base::FilePath pdf_file = test_data_dir->AppendASCII(file_name); + std::string pdf_data_str; + ASSERT_TRUE(base::ReadFileToString(pdf_file, &pdf_data_str)); + ASSERT_GT(pdf_data_str.length(), 0U); + *pdf_data = base::RefCountedString::TakeString(&pdf_data_str); +} + +std::string HashFile(const std::string& file_data) { + std::string sha1 = base::SHA1HashString(file_data); + return base::HexEncode(sha1.c_str(), sha1.length()); +} + +void ComparePwgFiles(const base::FilePath& expected, + const base::FilePath& actual) { + std::string pwg_expected_data_str; + ASSERT_TRUE(base::ReadFileToString(expected, &pwg_expected_data_str)); + std::string pwg_actual_data_str; + ASSERT_TRUE(base::ReadFileToString(actual, &pwg_actual_data_str)); + EXPECT_EQ(pwg_expected_data_str.length(), pwg_actual_data_str.length()); + EXPECT_EQ(HashFile(pwg_expected_data_str), HashFile(pwg_actual_data_str)); +} + class PdfToPwgRasterBrowserTest : public InProcessBrowserTest { public: PdfToPwgRasterBrowserTest() @@ -59,11 +98,6 @@ std::unique_ptr<PwgRasterConverter> converter_; }; -std::string HashFile(const std::string& file_data) { - std::string sha1 = base::SHA1HashString(file_data); - return base::HexEncode(sha1.c_str(), sha1.length()); -} - } // namespace IN_PROC_BROWSER_TEST_F(PdfToPwgRasterBrowserTest, TestFailure) { @@ -74,19 +108,12 @@ /*expect_success=*/false, &temp_file); } -IN_PROC_BROWSER_TEST_F(PdfToPwgRasterBrowserTest, TestSuccess) { +IN_PROC_BROWSER_TEST_F(PdfToPwgRasterBrowserTest, TestSuccessColor) { base::ScopedAllowBlockingForTesting allow_blocking; base::FilePath test_data_dir; - ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir)); - test_data_dir = test_data_dir.AppendASCII("printing"); - base::FilePath pdf_file = - test_data_dir.AppendASCII("pdf_to_pwg_raster_test.pdf"); - std::string pdf_data_str; - ASSERT_TRUE(base::ReadFileToString(pdf_file, &pdf_data_str)); - ASSERT_GT(pdf_data_str.length(), 0U); - scoped_refptr<base::RefCountedString> pdf_data( - base::RefCountedString::TakeString(&pdf_data_str)); + scoped_refptr<base::RefCountedString> pdf_data; + GetPdfData("pdf_to_pwg_raster_test.pdf", &test_data_dir, &pdf_data); PdfRenderSettings pdf_settings(gfx::Rect(0, 0, 500, 500), gfx::Point(0, 0), /*dpi=*/1000, /*autorotate=*/false, @@ -95,27 +122,42 @@ pwg_settings.odd_page_transform = PwgRasterTransformType::TRANSFORM_NORMAL; pwg_settings.rotate_all_pages = false; pwg_settings.reverse_page_order = false; + pwg_settings.use_color = true; base::FilePath temp_file; Convert(pdf_data.get(), pdf_settings, pwg_settings, /*expect_success=*/true, &temp_file); ASSERT_FALSE(temp_file.empty()); - // Note that for some reason the generated PWG varies depending on the - // platform (32 or 64 bits) on Linux. - base::FilePath pwg_file = test_data_dir.AppendASCII( -#if defined(OS_LINUX) && defined(ARCH_CPU_32_BITS) - "pdf_to_pwg_raster_test_32.pwg"); -#else - "pdf_to_pwg_raster_test.pwg"); -#endif + base::FilePath pwg_file = + test_data_dir.AppendASCII(kPdfToPwgRasterColorTestFile); + ComparePwgFiles(pwg_file, temp_file); +} - std::string pwg_expected_data_str; - ASSERT_TRUE(base::ReadFileToString(pwg_file, &pwg_expected_data_str)); - std::string pwg_actual_data_str; - ASSERT_TRUE(base::ReadFileToString(temp_file, &pwg_actual_data_str)); - EXPECT_EQ(pwg_expected_data_str.length(), pwg_actual_data_str.length()); - EXPECT_EQ(HashFile(pwg_expected_data_str), HashFile(pwg_actual_data_str)); +IN_PROC_BROWSER_TEST_F(PdfToPwgRasterBrowserTest, TestSuccessMono) { + base::ScopedAllowBlockingForTesting allow_blocking; + + base::FilePath test_data_dir; + scoped_refptr<base::RefCountedString> pdf_data; + GetPdfData("pdf_to_pwg_raster_test.pdf", &test_data_dir, &pdf_data); + + PdfRenderSettings pdf_settings(gfx::Rect(0, 0, 500, 500), gfx::Point(0, 0), + /*dpi=*/1000, /*autorotate=*/false, + PdfRenderSettings::Mode::NORMAL); + PwgRasterSettings pwg_settings; + pwg_settings.odd_page_transform = PwgRasterTransformType::TRANSFORM_NORMAL; + pwg_settings.rotate_all_pages = false; + pwg_settings.reverse_page_order = false; + pwg_settings.use_color = false; + + base::FilePath temp_file; + Convert(pdf_data.get(), pdf_settings, pwg_settings, + /*expect_success=*/true, &temp_file); + ASSERT_FALSE(temp_file.empty()); + + base::FilePath pwg_file = + test_data_dir.AppendASCII(kPdfToPwgRasterMonoTestFile); + ComparePwgFiles(pwg_file, temp_file); } } // namespace printing
diff --git a/chrome/browser/resource_coordinator/tab_manager_features.cc b/chrome/browser/resource_coordinator/tab_manager_features.cc index 6d80dad..52ace9a 100644 --- a/chrome/browser/resource_coordinator/tab_manager_features.cc +++ b/chrome/browser/resource_coordinator/tab_manager_features.cc
@@ -15,6 +15,17 @@ namespace features { +// Enables using customized value for tab load timeout. This is used by both +// staggered background tab opening and session restore in finch experiment to +// see what timeout value is better. The default timeout is used when this +// feature is disabled. +const base::Feature kCustomizedTabLoadTimeout{ + "CustomizedTabLoadTimeout", base::FEATURE_DISABLED_BY_DEFAULT}; + +// Enables proactive tab discarding. +const base::Feature kProactiveTabDiscarding{"ProactiveTabDiscarding", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Enables delaying the navigation of background tabs in order to improve // foreground tab's user experience. const base::Feature kStaggeredBackgroundTabOpening{ @@ -27,17 +38,84 @@ "StaggeredBackgroundTabOpeningExperiment", base::FEATURE_ENABLED_BY_DEFAULT}; -// Enables using customized value for tab load timeout. This is used by both -// staggered background tab opening and session restore in finch experiment to -// see what timeout value is better. The default timeout is used when this -// feature is disabled. -const base::Feature kCustomizedTabLoadTimeout{ - "CustomizedTabLoadTimeout", base::FEATURE_DISABLED_BY_DEFAULT}; - } // namespace features namespace resource_coordinator { +// Field-trial parameter names for proactive tab discarding. +const char kProactiveTabDiscard_LowLoadedTabCountParam[] = "LowLoadedTabCount"; +const char kProactiveTabDiscard_ModerateLoadedTabsPerGbRamParam[] = + "ModerateLoadedTabsPerGbRam"; +const char kProactiveTabDiscard_HighLoadedTabCountParam[] = + "HighLoadedTabCount"; +const char kProactiveTabDiscard_LowOccludedTimeoutParam[] = + "LowOccludedTimeoutSeconds"; +const char kProactiveTabDiscard_ModerateOccludedTimeoutParam[] = + "ModerateOccludedTimeoutSeconds"; +const char kProactiveTabDiscard_HighOccludedTimeoutParam[] = + "HighOccludedTimeoutSeconds"; + +// Default values for ProactiveTabDiscardParams. +// +// 50% of people cap out at 4 tabs, so for them proactive discarding won't even +// be invoked. See Tabs.MaxTabsInADay. +// TODO(chrisha): This should eventually be informed by the number of tabs +// typically used over a given time horizon (metric being developed). +const uint32_t kProactiveTabDiscard_LowLoadedTabCountDefault = 4; +// Testing in the lab shows that 2GB devices suffer beyond 6 tabs, and 4GB +// devices suffer beyond about 12 tabs. As a very simple first step, we'll aim +// at allowing 3 tabs per GB of RAM on a system before proactive discarding +// kicks in. This is a system resource dependent max, which is combined with the +// DefaultMaxLoadedTabCount to determine the max on a system. +const uint32_t kProactiveTabDiscard_ModerateLoadedTabsPerGbRamDefault = 3; +// 99.9% of people cap out with fewer than this number, so only 0.1% of the +// population should ever encounter proactive discarding based on this cap. +const uint32_t kProactiveTabDiscard_HighLoadedTabCountDefault = 100; +// Current discarding uses 10 minutes as a minimum cap. This uses exponentially +// increasing timeouts beyond that. +const base::TimeDelta kProactiveTabDiscard_LowOccludedTimeoutDefault = + base::TimeDelta::FromHours(6); +const base::TimeDelta kProactiveTabDiscard_ModerateOccludedTimeoutDefault = + base::TimeDelta::FromHours(1); +const base::TimeDelta kProactiveTabDiscard_HighOccludedTimeoutDefault = + base::TimeDelta::FromMinutes(10); + +void GetProactiveTabDiscardParams(ProactiveTabDiscardParams* params) { + params->low_loaded_tab_count = base::GetFieldTrialParamByFeatureAsInt( + features::kProactiveTabDiscarding, + kProactiveTabDiscard_LowLoadedTabCountParam, + kProactiveTabDiscard_LowLoadedTabCountDefault); + + params->moderate_loaded_tab_count_per_gb = + base::GetFieldTrialParamByFeatureAsInt( + features::kProactiveTabDiscarding, + kProactiveTabDiscard_ModerateLoadedTabsPerGbRamParam, + kProactiveTabDiscard_ModerateLoadedTabsPerGbRamDefault); + + params->high_loaded_tab_count = base::GetFieldTrialParamByFeatureAsInt( + features::kProactiveTabDiscarding, + kProactiveTabDiscard_HighLoadedTabCountParam, + kProactiveTabDiscard_HighLoadedTabCountDefault); + + params->low_occluded_timeout = + base::TimeDelta::FromSeconds(base::GetFieldTrialParamByFeatureAsInt( + features::kProactiveTabDiscarding, + kProactiveTabDiscard_LowOccludedTimeoutParam, + kProactiveTabDiscard_LowOccludedTimeoutDefault.InSeconds())); + + params->moderate_occluded_timeout = + base::TimeDelta::FromSeconds(base::GetFieldTrialParamByFeatureAsInt( + features::kProactiveTabDiscarding, + kProactiveTabDiscard_ModerateOccludedTimeoutParam, + kProactiveTabDiscard_ModerateOccludedTimeoutDefault.InSeconds())); + + params->high_occluded_timeout = + base::TimeDelta::FromSeconds(base::GetFieldTrialParamByFeatureAsInt( + features::kProactiveTabDiscarding, + kProactiveTabDiscard_HighOccludedTimeoutParam, + kProactiveTabDiscard_HighOccludedTimeoutDefault.InSeconds())); +} + base::TimeDelta GetTabLoadTimeout(const base::TimeDelta& default_timeout) { int timeout_in_ms = base::GetFieldTrialParamByFeatureAsInt( features::kCustomizedTabLoadTimeout, kTabLoadTimeoutInMsParameterName,
diff --git a/chrome/browser/resource_coordinator/tab_manager_features.h b/chrome/browser/resource_coordinator/tab_manager_features.h index 0da251c..570e86a 100644 --- a/chrome/browser/resource_coordinator/tab_manager_features.h +++ b/chrome/browser/resource_coordinator/tab_manager_features.h
@@ -10,14 +10,98 @@ namespace features { +extern const base::Feature kCustomizedTabLoadTimeout; +extern const base::Feature kProactiveTabDiscarding; extern const base::Feature kStaggeredBackgroundTabOpening; extern const base::Feature kStaggeredBackgroundTabOpeningExperiment; -extern const base::Feature kCustomizedTabLoadTimeout; } // namespace features namespace resource_coordinator { +// Variations parameter names related to proactive discarding. +// See ProactiveTabDiscardsParams for details. +extern const char kProactiveTabDiscard_LowLoadedTabCountParam[]; +extern const char kProactiveTabDiscard_ModerateLoadedTabsPerGbRamParam[]; +extern const char kProactiveTabDiscard_HighLoadedTabCountParam[]; +extern const char kProactiveTabDiscard_LowOccludedTimeoutParam[]; +extern const char kProactiveTabDiscard_ModerateOccludedTimeoutParam[]; +extern const char kProactiveTabDiscard_HighOccludedTimeoutParam[]; + +// Default values of parameters related to proactive discarding. +// See ProactiveTabDiscardsParams for details. +extern const uint32_t kProactiveTabDiscard_LowLoadedTabCountDefault; +extern const uint32_t kProactiveTabDiscard_ModerateLoadedTabsPerGbRamDefault; +extern const uint32_t kProactiveTabDiscard_HighLoadedTabCountDefault; +extern const base::TimeDelta kProactiveTabDiscard_LowOccludedTimeoutDefault; +extern const base::TimeDelta + kProactiveTabDiscard_ModerateOccludedTimeoutDefault; +extern const base::TimeDelta kProactiveTabDiscard_HighOccludedTimeoutDefault; + +// Parameters used by the proactive tab discarding feature. +// +// Proactive discarding has 5 key parameters: +// +// - min/max occluded timeouts +// - min/soft_max/hard_max loaded tab counts +// +// Proactive tab discarding decisions are made at two points in time: +// +// - when a new tab is created +// - when a max occluded timeout fires +// +// The following is a description of the initial simple proactive discarding +// logic. First, the number of loaded tabs is converted into one of 4 tab count +// states (LOW, MODERATE, HIGH, EXCESSIVE) using 3 simple thresholds. +// +// +-------+----------+---------+-----------+ +// + LOW | MODERATE | HIGH | EXCESSIVE | +// +-------+----------+---------+-----------+ +// 0 n_low n_mod n_high +inf +// +// Depending on the tab count state, tabs are eligible for proactive discarding +// at different time tresholds, where the timeout is longer for lower tab +// count states. When in the low state the timeout is effectively infinite (no +// proactive discarding will occur), and when in the excessive state the timeout +// is zero (discarding will occur immediately). +// +// This logic is independent of urgent discarding, which may embark when things +// are sufficiently bad. Similarly, manual or extension driven discards can +// override this logic. Finally, proactive discarding can only discard occluded +// tabs, so it is always possible to have arbitrarily many visible tabs. +// +// NOTE: This is extremely simplistic, and by design. We will be using this to +// do a very simple "lightspeed" experiment to determine how much possible +// savings proactive discarding can hope to achieve. +struct ProactiveTabDiscardParams { + // Tab count (inclusive) beyond which the state transitions to MODERATE. + // Intended to cover the majority of simple workflows and be small enough that + // it is very unlikely that memory pressure will be encountered with this many + // tabs loaded. + int low_loaded_tab_count; + // Tab count (inclusive) beyond which the state transitions to HIGH, expressed + // relative to system memory. + int moderate_loaded_tab_count_per_gb; + // Tab count (inclusive) beyond which the state transitions to EXCESSIVE. + // Not expressed relative to system memory, as its intended to be a hard cap + // more akin to a maximum mental model size. + int high_loaded_tab_count; + // Amount of time a tab must be occluded before eligible for proactive + // discard when the tab count state is LOW. + base::TimeDelta low_occluded_timeout; + // Amount of time a tab must be occluded before eligible for proactive + // discard when the tab count state is MODERATE. + base::TimeDelta moderate_occluded_timeout; + // Amount of time a tab must be occluded before eligible for proactive + // discard when the tab count state is HIGH. + base::TimeDelta high_occluded_timeout; +}; + +// Gets parameters for the proactive tab discarding feature. This does no +// parameter validation, and sets the default values if the feature is not +// enabled. +void GetProactiveTabDiscardParams(ProactiveTabDiscardParams* params); + base::TimeDelta GetTabLoadTimeout(const base::TimeDelta& default_timeout); } // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/tab_manager_features_unittest.cc b/chrome/browser/resource_coordinator/tab_manager_features_unittest.cc new file mode 100644 index 0000000..877efe6c --- /dev/null +++ b/chrome/browser/resource_coordinator/tab_manager_features_unittest.cc
@@ -0,0 +1,104 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/resource_coordinator/tab_manager_features.h" + +#include "base/macros.h" +#include "base/metrics/field_trial.h" +#include "base/strings/string_piece.h" +#include "components/variations/variations_params_manager.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace resource_coordinator { + +namespace { + +class TabManagerFeaturesTest : public testing::Test { + public: + // Enables the proactive tab discarding feature, and sets up the associated + // variations parameter values. + void EnableProactiveTabDiscarding() { + std::set<std::string> features; + features.insert(features::kProactiveTabDiscarding.name); + variations_manager_.SetVariationParamsWithFeatureAssociations( + "DummyTrial", params_, features); + } + + void SetParam(base::StringPiece key, base::StringPiece value) { + params_[key.as_string()] = value.as_string(); + } + + void ExpectProactiveTabDiscardingParams( + int low_loaded_tab_count, + int moderate_loaded_tab_count_per_gb, + int high_loaded_tab_count, + base::TimeDelta low_occluded_timeout, + base::TimeDelta moderate_occluded_timeout, + base::TimeDelta high_occluded_timeout) { + ProactiveTabDiscardParams params = {}; + GetProactiveTabDiscardParams(¶ms); + EXPECT_EQ(low_loaded_tab_count, params.low_loaded_tab_count); + EXPECT_EQ(moderate_loaded_tab_count_per_gb, + params.moderate_loaded_tab_count_per_gb); + EXPECT_EQ(high_loaded_tab_count, params.high_loaded_tab_count); + EXPECT_EQ(low_occluded_timeout, params.low_occluded_timeout); + EXPECT_EQ(moderate_occluded_timeout, params.moderate_occluded_timeout); + EXPECT_EQ(high_occluded_timeout, params.high_occluded_timeout); + } + + void ExpectDefaultProactiveTabDiscardParams() { + ExpectProactiveTabDiscardingParams( + kProactiveTabDiscard_LowLoadedTabCountDefault, + kProactiveTabDiscard_ModerateLoadedTabsPerGbRamDefault, + kProactiveTabDiscard_HighLoadedTabCountDefault, + kProactiveTabDiscard_LowOccludedTimeoutDefault, + kProactiveTabDiscard_ModerateOccludedTimeoutDefault, + kProactiveTabDiscard_HighOccludedTimeoutDefault); + } + + private: + std::map<std::string, std::string> params_; + variations::testing::VariationParamsManager variations_manager_; +}; + +} // namespace + +TEST_F(TabManagerFeaturesTest, + GetProactiveTabDiscardParamsDisabledFeatureGoesToDefault) { + // Do not enable the proactive tab discarding feature. + ExpectDefaultProactiveTabDiscardParams(); +} + +TEST_F(TabManagerFeaturesTest, GetProactiveTabDiscardParamsNoneGoesToDefault) { + EnableProactiveTabDiscarding(); + ExpectDefaultProactiveTabDiscardParams(); +} + +TEST_F(TabManagerFeaturesTest, + GetProactiveTabDiscardParamsInvalidGoesToDefault) { + SetParam(kProactiveTabDiscard_LowLoadedTabCountParam, "ab"); + SetParam(kProactiveTabDiscard_ModerateLoadedTabsPerGbRamParam, "27.8"); + SetParam(kProactiveTabDiscard_HighLoadedTabCountParam, "4e8"); + SetParam(kProactiveTabDiscard_LowOccludedTimeoutParam, "---"); + SetParam(kProactiveTabDiscard_ModerateOccludedTimeoutParam, " "); + SetParam(kProactiveTabDiscard_HighOccludedTimeoutParam, ""); + EnableProactiveTabDiscarding(); + ExpectDefaultProactiveTabDiscardParams(); +} + +TEST_F(TabManagerFeaturesTest, GetProactiveTabDiscardParams) { + SetParam(kProactiveTabDiscard_LowLoadedTabCountParam, "7"); + SetParam(kProactiveTabDiscard_ModerateLoadedTabsPerGbRamParam, "19"); + SetParam(kProactiveTabDiscard_HighLoadedTabCountParam, "42"); + // These are expressed in seconds. + SetParam(kProactiveTabDiscard_LowOccludedTimeoutParam, "60"); + SetParam(kProactiveTabDiscard_ModerateOccludedTimeoutParam, "120"); + SetParam(kProactiveTabDiscard_HighOccludedTimeoutParam, "247"); + EnableProactiveTabDiscarding(); + ExpectProactiveTabDiscardingParams( + 7, 19, 42, base::TimeDelta::FromSeconds(60), + base::TimeDelta::FromSeconds(120), base::TimeDelta::FromSeconds(247)); +} + +} // namespace resource_coordinator
diff --git a/chrome/browser/resources/chromeos/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/chromevox/BUILD.gn index 6e5018a..98fdb591 100644 --- a/chrome/browser/resources/chromeos/chromevox/BUILD.gn +++ b/chrome/browser/resources/chromeos/chromevox/BUILD.gn
@@ -148,7 +148,6 @@ "cvox2/background/panel_menu.js", "cvox2/background/panel_menu_item.js", "cvox2/background/recovery_strategy.js", - "cvox2/background/tabs_automation_handler.js", "cvox2/background/tree_walker.js", "cvox2/background/tutorial.js", "cvox2/injected/keyboard_handler.js",
diff --git a/chrome/browser/resources/chromeos/chromevox/braille/braille_input_handler.js b/chrome/browser/resources/chromeos/chromevox/braille/braille_input_handler.js index 7e83ab4..c7f09b92 100644 --- a/chrome/browser/resources/chromeos/chromevox/braille/braille_input_handler.js +++ b/chrome/browser/resources/chromeos/chromevox/braille/braille_input_handler.js
@@ -421,14 +421,6 @@ chrome.virtualKeyboardPrivate.getKeyboardConfig(function(config) { // Use the virtual keyboard API instead of the IME key event API // so that these keys work even if the Braille IME is not active. - - // The virtual keyboard private api fails silently if the a11y keyboard - // isn't enabled in settings. Let the user know. - if (!config.a11ymode) { - new Output().format('@enable_virtual_keyboard').go(); - return; - } - var keyName = /** @type {string} */ (event.standardKeyCode); var numericCode = cvox.BrailleKeyEvent.keyCodeToLegacyCode(keyName); if (!goog.isDef(numericCode))
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/background/tabs_api_handler.js b/chrome/browser/resources/chromeos/chromevox/chromevox/background/tabs_api_handler.js index c46fce6..af42af01 100644 --- a/chrome/browser/resources/chromeos/chromevox/chromevox/background/tabs_api_handler.js +++ b/chrome/browser/resources/chromeos/chromevox/chromevox/background/tabs_api_handler.js
@@ -9,7 +9,6 @@ goog.provide('cvox.TabsApiHandler'); -goog.require('TabsAutomationHandler'); goog.require('cvox.AbstractEarcons'); goog.require('cvox.AbstractTts'); goog.require('cvox.BrailleInterface'); @@ -73,9 +72,6 @@ cvox.NavBraille.fromText(this.msg_('chrome_tab_created'))); } cvox.ChromeVox.earcons.playEarcon(cvox.Earcon.OBJECT_OPEN); - if (tab) { - this.refreshAutomationHandler_(tab.id); - } }, /** @@ -115,7 +111,6 @@ this.msg_('chrome_tab_selected', [title]))); } cvox.ChromeVox.earcons.playEarcon(cvox.Earcon.OBJECT_SELECT); - this.refreshAutomationHandler_(tab.id); }.bind(this)); }, @@ -161,7 +156,6 @@ cvox.ChromeVox.earcons.playEarcon(cvox.Earcon.PAGE_FINISH_LOADING); this.cancelPageLoadTimer_(); } - this.refreshAutomationHandler_(tabId); }.bind(this)); }, @@ -193,30 +187,11 @@ cvox.NavBraille.fromText(this.msg_(msgId, [title]))); } cvox.ChromeVox.earcons.playEarcon(cvox.Earcon.OBJECT_SELECT); - this.refreshAutomationHandler_(tab.id); }.bind(this)); }.bind(this)); }, /** - * Installs a new automation handler for the given tab. - * @param {number} tabId - * @private - */ - refreshAutomationHandler_: function(tabId) { - if (!cvox.ChromeVox.isMac || - ChromeVoxState.instance.mode == ChromeVoxMode.CLASSIC) - return; - - chrome.automation.getTree(tabId, function(node) { - if (this.handler_) - this.handler_.removeAllListeners(); - - this.handler_ = new TabsAutomationHandler(node); - }.bind(this)); - }, - - /** * The chrome.tabs API doesn't always fire an onUpdated event when a * page finishes loading, so we poll it. * @param {number} tabId The id of the tab to monitor.
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js index 752cc608..1460182 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js
@@ -15,6 +15,7 @@ goog.require('BrailleCommandHandler'); goog.require('ChromeVoxState'); goog.require('CommandHandler'); +goog.require('DesktopAutomationHandler'); goog.require('FindHandler'); goog.require('LiveRegions'); goog.require('MediaAutomationHandler'); @@ -28,7 +29,6 @@ goog.require('cvox.BrailleKeyCommand'); goog.require('cvox.ChromeVoxBackground'); goog.require('cvox.ChromeVoxEditableTextBase'); -goog.require('cvox.ClassicEarcons'); goog.require('cvox.ExtensionBridge'); goog.require('cvox.NavBraille'); @@ -56,22 +56,6 @@ this.whitelist_ = ['chromevox_next_test']; /** - * A list of site substring patterns to blacklist ChromeVox Classic, - * putting ChromeVox into classic Compat mode. - * @type {!Set<string>} - * @private - */ - this.classicBlacklist_ = new Set(); - - /** - * Regular expression for blacklisting classic. - * @type {RegExp} - * @private - */ - this.classicBlacklistRegExp_ = Background.globsToRegExp_( - chrome.runtime.getManifest()['content_scripts'][0]['exclude_globs']); - - /** * @type {cursors.Range} * @private */ @@ -84,31 +68,19 @@ } /** @type {!cvox.AbstractEarcons} @private */ - this.classicEarcons_ = cvox.ChromeVox.earcons || new cvox.ClassicEarcons(); - - /** @type {!cvox.AbstractEarcons} @private */ this.nextEarcons_ = new NextEarcons(); - // Turn cvox.ChromeVox.earcons into a getter that returns either the - // Next earcons or the Classic earcons depending on the current mode. + // Read-only earcons. Object.defineProperty(cvox.ChromeVox, 'earcons', { get: (function() { - if (this.mode === ChromeVoxMode.FORCE_NEXT || - this.mode === ChromeVoxMode.NEXT) { - return this.nextEarcons_; - } else { - return this.classicEarcons_; - } + return this.nextEarcons_; }).bind(this) }); if (cvox.ChromeVox.isChromeOS) { Object.defineProperty(cvox.ChromeVox, 'modKeyStr', { get: function() { - return (this.mode == ChromeVoxMode.CLASSIC || - this.mode == ChromeVoxMode.CLASSIC_COMPAT) ? - 'Search+Shift' : - 'Search'; + return 'Search'; }.bind(this) }); @@ -149,13 +121,6 @@ /** @type {!LiveRegions} @private */ this.liveRegions_ = new LiveRegions(this); - /** - * Stores the mode as computed the last time a current range was set. - * @type {?ChromeVoxMode} - * @private - */ - this.mode_ = null; - chrome.accessibilityPrivate.onAccessibilityGesture.addListener( this.onAccessibilityGesture_); @@ -179,37 +144,19 @@ this.chromeChannel_ = desktop.chromeChannel; }.bind(this)); - // Record a metric with the mode we're in on startup. - var useNext = localStorage['useClassic'] != 'true'; - chrome.metricsPrivate.recordBoolean( - 'Accessibility.CrosChromeVoxNext', useNext); + CommandHandler.init(); + FindHandler.init(); Notifications.onStartup(); }; /** * Map from gesture names (AXGesture defined in ui/accessibility/ax_enums.idl) - * to commands when in Classic mode. + * to commands. * @type {Object<string, string>} * @const */ -Background.GESTURE_CLASSIC_COMMAND_MAP = { - 'click': 'forceClickOnCurrentItem', - 'swipeUp1': 'backward', - 'swipeDown1': 'forward', - 'swipeLeft1': 'left', - 'swipeRight1': 'right', - 'swipeUp2': 'jumpToTop', - 'swipeDown2': 'readFromHere', -}; - -/** - * Map from gesture names (AXGesture defined in ui/accessibility/ax_enums.idl) - * to commands when in Classic mode. - * @type {Object<string, string>} - * @const - */ -Background.GESTURE_NEXT_COMMAND_MAP = { +Background.GESTURE_COMMAND_MAP = { 'click': 'forceClickOnCurrentItem', 'swipeUp1': 'previousLine', 'swipeDown1': 'nextLine', @@ -234,110 +181,6 @@ /** * @override */ - getMode: function() { - var useNext = localStorage['useClassic'] !== 'true'; - - var target; - if (!this.getCurrentRange()) { - chrome.automation.getFocus(function(focus) { - target = focus; - }); - } else { - target = this.getCurrentRange().start.node; - } - - if (!target) - return useNext ? ChromeVoxMode.FORCE_NEXT : ChromeVoxMode.CLASSIC; - - // Closure complains, but clearly, |target| is not null. - var topLevelRoot = - AutomationUtil.getTopLevelRoot(/** @type {!AutomationNode} */ (target)); - if (!topLevelRoot) - return useNext ? ChromeVoxMode.FORCE_NEXT : ChromeVoxMode.CLASSIC_COMPAT; - - var docUrl = topLevelRoot.docUrl || ''; - var nextSite = this.isWhitelistedForNext_(docUrl); - var classicCompat = this.isWhitelistedForClassicCompat_(docUrl); - if (classicCompat && !useNext) - return ChromeVoxMode.CLASSIC_COMPAT; - else if (nextSite) - return ChromeVoxMode.NEXT; - else if (!useNext) - return ChromeVoxMode.CLASSIC; - else - return ChromeVoxMode.FORCE_NEXT; - }, - - /** - * Handles a mode change. - * @param {ChromeVoxMode} newMode - * @param {?ChromeVoxMode} oldMode Can be null at startup when no range was - * previously set. - * @private - */ - onModeChanged_: function(newMode, oldMode) { - this.keyboardHandler_.onModeChanged(newMode, oldMode); - CommandHandler.onModeChanged(newMode, oldMode); - FindHandler.onModeChanged(newMode, oldMode); - - // The below logic handles transition between the classic engine - // (content script) and next engine (no content script) as well as - // misc states that are not handled above. - - // Classic modes do not use the new focus highlight. - if (newMode == ChromeVoxMode.CLASSIC) - chrome.accessibilityPrivate.setFocusRing([]); - - // Switch on/off content scripts. - // note that |this.currentRange_| can *change* because the request is - // async. Save it to ensure we're looking at the currentRange at this moment - // in time. - var cur = this.currentRange_; - chrome.tabs.query({active: true, lastFocusedWindow: true}, function(tabs) { - if (newMode == ChromeVoxMode.CLASSIC) { - // Generally, we don't want to inject classic content scripts as it is - // done by the extension system at document load. The exception is when - // we toggle classic on manually as part of a user command. - if (oldMode == ChromeVoxMode.FORCE_NEXT) { - cvox.ChromeVox.injectChromeVoxIntoTabs(tabs); - } - } else if (newMode === ChromeVoxMode.FORCE_NEXT) { - this.disableClassicChromeVox_(); - } else { - // If we're focused in the desktop tree, do nothing. - if (cur && !cur.isWebRange()) - return; - - // If we're entering classic compat mode or next mode for just one tab, - // disable Classic for that tab only. - this.disableClassicChromeVox_(tabs); - } - }.bind(this)); - - // Switching into either compat or classic. - if (oldMode === ChromeVoxMode.NEXT || - oldMode === ChromeVoxMode.FORCE_NEXT) { - // Make sure we cancel the progress loading sound just in case. - cvox.ChromeVox.earcons.cancelEarcon(cvox.Earcon.PAGE_START_LOADING); - (new PanelCommand(PanelCommandType.DISABLE_MENUS)).send(); - } - - // Switching out of next, force next, or uninitialized (on startup). - if (newMode === ChromeVoxMode.NEXT || - newMode === ChromeVoxMode.FORCE_NEXT) { - (new PanelCommand(PanelCommandType.ENABLE_MENUS)).send(); - if (cvox.TabsApiHandler) - cvox.TabsApiHandler.shouldOutputSpeechAndBraille = false; - } else { - // |newMode| is either classic or compat. - if (cvox.TabsApiHandler) - cvox.TabsApiHandler.shouldOutputSpeechAndBraille = true; - } - }, - - /** - * @override - */ getCurrentRange: function() { if (this.currentRange_ && this.currentRange_.isValid()) return this.currentRange_; @@ -359,12 +202,6 @@ ChromeVoxState.observers.forEach(function(observer) { observer.onCurrentRangeChanged(newRange); }); - var oldMode = this.mode_; - var newMode = this.getMode(); - if (oldMode != newMode) { - this.onModeChanged_(newMode, oldMode); - this.mode_ = newMode; - } if (this.currentRange_) { var start = this.currentRange_.start.node; @@ -481,9 +318,6 @@ * @return {boolean} True if evt was processed. */ onBrailleKeyEvent: function(evt, content) { - if (this.mode === ChromeVoxMode.CLASSIC) - return false; - switch (evt.command) { case cvox.BrailleKeyCommand.PAN_LEFT: CommandHandler.onCommand('previousObject'); @@ -514,8 +348,13 @@ return false; var command = BrailleCommandHandler.getCommand(evt.brailleDots); - if (command) - CommandHandler.onCommand(command); + if (command) { + if (!ChromeVoxState.instance.currentRange || + !ChromeVoxState.instance.currentRange.start.node + .state[StateType.EDITABLE] || + BrailleCommandHandler.onEditCommand(command)) + CommandHandler.onCommand(command); + } break; default: return false; @@ -524,73 +363,6 @@ }, /** - * Returns true if the url should have Classic running. - * @return {boolean} - * @private - */ - shouldEnableClassicForUrl_: function(url) { - return this.mode != ChromeVoxMode.FORCE_NEXT && - !this.isBlacklistedForClassic_(url) && !this.isWhitelistedForNext_(url); - }, - - /** - * Compat mode is on if any of the following are true: - * 1. a url is blacklisted for Classic. - * 2. the current range is not within web content. - * @param {string} url - * @return {boolean} - */ - isWhitelistedForClassicCompat_: function(url) { - return (this.isBlacklistedForClassic_(url) || - (this.getCurrentRange() && !this.getCurrentRange().isWebRange() && - this.getCurrentRange().start.node.state[StateType.FOCUSED])) || - false; - }, - - /** - * @param {string} url - * @return {boolean} - * @private - */ - isBlacklistedForClassic_: function(url) { - if (this.classicBlacklistRegExp_.test(url)) - return true; - url = url.substring(0, url.indexOf('#')) || url; - return this.classicBlacklist_.has(url); - }, - - /** - * @param {string} url - * @return {boolean} Whether the given |url| is whitelisted. - * @private - */ - isWhitelistedForNext_: function(url) { - return this.whitelist_.some(function(item) { - return url.indexOf(item) != -1; - }); - }, - - /** - * Disables classic ChromeVox in current web content. - * @param {Array<Tab>=} opt_tabs The tabs where ChromeVox scripts should be - * disabled. If null, will disable ChromeVox everywhere. - */ - disableClassicChromeVox_: function(opt_tabs) { - var disableChromeVoxCommand = { - message: 'SYSTEM_COMMAND', - command: 'killChromeVox' - }; - - if (opt_tabs) { - for (var i = 0, tab; tab = opt_tabs[i]; i++) - chrome.tabs.sendMessage(tab.id, disableChromeVoxCommand); - } else { - // Send to all ChromeVox clients. - cvox.ExtensionBridge.send(disableChromeVoxCommand); - } - }, - - /** * @param {!Spannable} text * @param {number} position * @private @@ -667,14 +439,9 @@ case 'next': if (action == 'getIsClassicEnabled') { var url = msg['url']; - var isClassicEnabled = this.shouldEnableClassicForUrl_(url); + var isClassicEnabled = false; port.postMessage( {target: 'next', isClassicEnabled: isClassicEnabled}); - } else if (action == 'enableClassicCompatForUrl') { - var url = msg['url']; - this.classicBlacklist_.add(url); - if (this.currentRange_ && this.currentRange_.start.node) - this.setCurrentRange(this.currentRange_); } else if (action == 'onCommand') { CommandHandler.onCommand(msg['command']); } else if (action == 'flushNextUtterance') { @@ -703,38 +470,12 @@ * @private */ onAccessibilityGesture_: function(gesture) { - // If we're in classic mode, some gestures need to be handled by the - // content script. Other gestures are universal and will be handled in - // this function. - if (this.mode == ChromeVoxMode.CLASSIC) { - if (this.handleClassicGesture_(gesture)) - return; - } - - var command = Background.GESTURE_NEXT_COMMAND_MAP[gesture]; + var command = Background.GESTURE_COMMAND_MAP[gesture]; if (command) CommandHandler.onCommand(command); }, /** - * Handles accessibility gestures from the touch screen when in CLASSIC - * mode, by forwarding a command to the content script. - * @param {string} gesture The gesture to handle, based on the AXGesture enum - * defined in ui/accessibility/ax_enums.idl - * @return {boolean} True if this gesture was handled. - * @private - */ - handleClassicGesture_: function(gesture) { - var command = Background.GESTURE_CLASSIC_COMMAND_MAP[gesture]; - if (!command) - return false; - - var msg = {'message': 'USER_COMMAND', 'command': command}; - cvox.ExtensionBridge.send(msg); - return true; - }, - - /** * Detects various clipboard events and provides spoken output. * * Note that paste is explicitly skipped sometimes because during a copy or
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs index 670cc2dd..eed2f17 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs
@@ -24,9 +24,9 @@ setUp: function() { window.RoleType = chrome.automation.RoleType; window.doCmd = this.doCmd; + window.press = this.press; + window.Mod = constants.ModifierFlag; - // Reset notifications so only explicit mode changes can cause them to trigger. - Notifications.reset(); this.forceContextualLastOutput(); }, @@ -51,6 +51,12 @@ }; }, + press: function(keyCode, keyName, modifiers) { + return function() { + BackgroundKeyboardHandler.sendKeyPress(keyCode, keyName, modifiers); + }; + }, + linksAndHeadingsDoc: function() {/*! <p>start</p> <a href='#a'>alpha</a> @@ -451,6 +457,10 @@ .call(doCmd('nextObject')) .expectSpeech('Edit text') .expectEarcon(cvox.Earcon.EDITABLE_TEXT) + + // Editable text Search re-mappings are in effect. + .call(doCmd('toggleStickyMode')) + .expectSpeech('Sticky mode enabled') .call(doCmd('nextObject')) .expectSpeech('List box') .expectEarcon(cvox.Earcon.LISTBOX) @@ -514,78 +524,6 @@ }); }); -TEST_F('BackgroundTest', 'ModeSwitching', function() { - this.runWithLoadedTree('<button></button>', function(root) { - var fakeDesktop = {}; - fakeDesktop.role = 'desktop'; - fakeDesktop.root = fakeDesktop; - - var fakeWebRoot = {}; - fakeWebRoot.root = fakeWebRoot; - fakeWebRoot.parent = fakeDesktop; - fakeWebRoot.role = RoleType.ROOT_WEB_AREA; - fakeWebRoot.makeVisible = function() {}; - fakeWebRoot.unclippedLocation = {left: 1, top: 1, width: 1, height: 1}; - var fakeSubRoot = {}; - fakeSubRoot.root = fakeSubRoot; - fakeSubRoot.parent = fakeWebRoot; - fakeSubRoot.role = RoleType.ROOT_WEB_AREA; - fakeSubRoot.makeVisible = function() {}; - fakeSubRoot.unclippedLocation = {left: 1, top: 1, width: 1, height: 1}; - var bk = ChromeVoxState.instance; - - // Tests default to force next mode. - assertEquals('force_next', bk.mode); - - // Force next mode stays set regardless of where the range lands. - fakeWebRoot.docUrl = 'http://google.com'; - bk.setCurrentRange(cursors.Range.fromNode(fakeWebRoot)); - assertEquals('force_next', bk.mode); - // Empty urls occur before document load or when root is desktop. - fakeWebRoot.docUrl = ''; - bk.setCurrentRange(cursors.Range.fromNode(fakeWebRoot)); - assertEquals('force_next', bk.mode); - - // Verify force next -> classic compat switching. - localStorage['useClassic'] = true; - fakeWebRoot.docUrl = 'chrome://foobar'; - bk.setCurrentRange(cursors.Range.fromNode(fakeWebRoot)); - assertEquals('classic_compat', bk.mode); - - // Classic compat -> classic. - fakeWebRoot.docUrl = 'http://google.com'; - bk.setCurrentRange(cursors.Range.fromNode(fakeWebRoot)); - assertEquals('classic', bk.mode); - - // Ensure we switch to classic compat if our current range has focused - // state set and is not in web content. - assertTrue(root.parent.state.focused); - bk.setCurrentRange(cursors.Range.fromNode(root.parent)); - assertEquals('classic_compat', bk.mode); - - // And back to classic. - bk.setCurrentRange(cursors.Range.fromNode(root)); - assertEquals('classic', bk.mode); - - // Now, verify mode switching uses the top level root. - fakeWebRoot.docUrl = 'http://google.com/#chromevox_next_test'; - fakeSubRoot.docUrl = 'http://chromevox.com'; - bk.setCurrentRange(cursors.Range.fromNode(fakeWebRoot)); - assertEquals('next', bk.mode); - - // Next compat switching. - localStorage['useClassic'] = false; - fakeWebRoot.docUrl = 'http://docs.google.com/document/#123123'; - bk.setCurrentRange(cursors.Range.fromNode(fakeWebRoot)); - assertEquals('force_next', bk.mode); - - // And, back to force next. - fakeWebRoot.docUrl = 'http://docs.google.com/form/123'; - bk.setCurrentRange(cursors.Range.fromNode(fakeWebRoot)); - assertEquals('force_next', bk.mode); - }.bind(this)); -}); - TEST_F('BackgroundTest', 'ShouldNotFocusIframe', function() { this.runWithLoadedTree( function() {/*! <iframe tabindex=0 src="data:text/html,<p>Inside</p>"></iframe> @@ -758,18 +696,22 @@ return; running = true; + var suppressFocusActionOutput = function() { + DesktopAutomationHandler.announceActions = false; + }; var beforeButton = rootNode.find({role: RoleType.BUTTON, name: 'Before'}); - beforeButton.focus(); - mockFeedback.expectSpeech('Before', 'Button'); - mockFeedback.call(doCmd('nextObject')) + mockFeedback.call(beforeButton.focus.bind(beforeButton)) + .expectSpeech('Before', 'Button') + .call(suppressFocusActionOutput) + .call(doCmd('nextObject')) .expectSpeech('Inside', 'Button'); mockFeedback.call(doCmd('nextObject')) .expectSpeech('Inside', 'Heading 1'); mockFeedback.call(doCmd('nextObject')) .expectSpeech('After', 'Button'); mockFeedback.call(doCmd('previousObject')) - .expectSpeech('Heading 1', 'Inside'); + .expectSpeech('Inside', 'Heading 1'); mockFeedback.call(doCmd('previousObject')) .expectSpeech('Inside', 'Button'); mockFeedback.call(doCmd('previousObject')) @@ -1342,3 +1284,20 @@ .replay(); }); }); + +TEST_F('BackgroundTest', 'NativeFind', function() { + var mockFeedback = this.createMockFeedback(); + this.runWithLoadedTree(function(root) {/*! + <a href="#">grape</a> + <a href="#">pineapple</a> + */}, function(root) { + mockFeedback.call(press(70, 'F', Mod.CONTROL)) + .expectSpeech('Find', 'Edit text') + .call(press(71, 'G')) + .expectSpeech('grape', 'Link') + .call(press(8, 'Backspace')) + .call(press(76, 'L')) + .expectSpeech('pineapple', 'Link') + .replay(); + }); +});
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/braille_command_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/braille_command_handler.js index 9cc7d0c..9aa65f4 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/braille_command_handler.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/braille_command_handler.js
@@ -8,7 +8,11 @@ goog.provide('BrailleCommandHandler'); +goog.require('BackgroundKeyboardHandler'); + goog.scope(function() { +var Mod = constants.ModifierFlag; + /** * Maps a dot pattern to a command. * @type {!Object<number, string>} @@ -88,6 +92,46 @@ }; /** + * Customizes ChromeVox commands when issued from a braille display while within + * editable text. + * @param {string} command + * @return {boolean} True if the command should propagate. + */ +BrailleCommandHandler.onEditCommand = function(command) { + switch (command) { + case 'previousCharacter': + BackgroundKeyboardHandler.sendKeyPress(37, 'ArrowLeft'); + break; + case 'nextCharacter': + BackgroundKeyboardHandler.sendKeyPress(39, 'ArrowRight'); + break; + case 'previousWord': + BackgroundKeyboardHandler.sendKeyPress(37, 'ArrowLeft', Mod.CONTROL); + break; + case 'nextWord': + BackgroundKeyboardHandler.sendKeyPress(39, 'ArrowRight', Mod.CONTROL); + break; + case 'previousObject': + case 'previousLine': + BackgroundKeyboardHandler.sendKeyPress(38, 'ArrowUp'); + break; + case 'nextObject': + case 'nextLine': + BackgroundKeyboardHandler.sendKeyPress(40, 'ArrowDown'); + break; + case 'previousGroup': + BackgroundKeyboardHandler.sendKeyPress(38, 'ArrowUp', Mod.CONTROL); + break; + case 'nextGroup': + BackgroundKeyboardHandler.sendKeyPress(40, 'ArrowDown', Mod.CONTROL); + break; + default: + return true; + } + return false; +}; + +/** * @private */ BrailleCommandHandler.init_ = function() {
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/chromevox_state.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/chromevox_state.js index 9304206..68b5120 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/chromevox_state.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/chromevox_state.js
@@ -8,7 +8,6 @@ * object and to facilitate mocking for tests. */ -goog.provide('ChromeVoxMode'); goog.provide('ChromeVoxState'); goog.provide('ChromeVoxStateObserver'); @@ -16,17 +15,6 @@ goog.require('cursors.Range'); /** - * All possible modes ChromeVox can run. - * @enum {string} - */ -ChromeVoxMode = { - CLASSIC: 'classic', - CLASSIC_COMPAT: 'classic_compat', - NEXT: 'next', - FORCE_NEXT: 'force_next' -}; - -/** * An interface implemented by objects that want to observe ChromeVox state * changes. * @interface @@ -67,19 +55,6 @@ ChromeVoxState.isReadingContinuously; ChromeVoxState.prototype = { - /** @type {ChromeVoxMode} */ - get mode() { - return this.getMode(); - }, - - /** - * @return {ChromeVoxMode} The current mode. - * @protected - */ - getMode: function() { - return ChromeVoxMode.NEXT; - }, - /** @type {cursors.Range} */ get currentRange() { return this.getCurrentRange();
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/command_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/command_handler.js index 95babd2..e0e8f5b 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/command_handler.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/command_handler.js
@@ -12,13 +12,16 @@ goog.require('CustomAutomationEvent'); goog.require('Output'); goog.require('cvox.ChromeVoxBackground'); +goog.require('cvox.ChromeVoxKbHandler'); goog.scope(function() { var AutomationEvent = chrome.automation.AutomationEvent; var AutomationNode = chrome.automation.AutomationNode; var Dir = constants.Dir; +var Mod = constants.ModifierFlag; var EventType = chrome.automation.EventType; var RoleType = chrome.automation.RoleType; +var StateType = chrome.automation.StateType; /** * Handles ChromeVox Next commands. @@ -39,7 +42,7 @@ ChromeVoxState.instance.setCurrentRange(null); }); - // These commands don't require a current range and work in all modes. + // These commands don't require a current range. switch (command) { case 'speakTimeAndDate': chrome.automation.getDesktop(function(d) { @@ -97,8 +100,11 @@ Msgs.getMsg('pass_through_key'), cvox.QueueMode.QUEUE); return true; case 'showKbExplorerPage': - var explorerPage = {url: 'chromevox/background/kbexplorer.html'}; - chrome.tabs.create(explorerPage); + var explorerPage = { + url: 'chromevox/background/kbexplorer.html', + type: 'panel' + }; + chrome.windows.create(explorerPage); break; case 'decreaseTtsRate': CommandHandler.increaseOrDecreaseSpeechProperty_( @@ -170,7 +176,6 @@ 'description='; var description = {}; - description['Mode'] = ChromeVoxState.instance.mode; description['Version'] = chrome.app.getDetails().version; description['Reproduction Steps'] = '%0a1.%0a2.%0a3.'; for (var key in description) @@ -237,11 +242,12 @@ if (!ChromeVoxState.instance.currentRange_) return true; - // Next/classic compat commands hereafter. - if (ChromeVoxState.instance.mode == ChromeVoxMode.CLASSIC) - return true; - var current = ChromeVoxState.instance.currentRange_; + + // Allow edit commands first. + if (!CommandHandler.onEditCommand_(current, command)) + return false; + var dir = Dir.FORWARD; var pred = null; var predErrorMsg = undefined; @@ -813,24 +819,6 @@ }; /** - * React to mode changes. - * @param {ChromeVoxMode} newMode - * @param {ChromeVoxMode?} oldMode - */ -CommandHandler.onModeChanged = function(newMode, oldMode) { - // Previously uninitialized. - if (!oldMode) - cvox.ChromeVoxKbHandler.commandHandler = CommandHandler.onCommand; - - var hasListener = - chrome.commands.onCommand.hasListener(CommandHandler.onCommand); - if (newMode == ChromeVoxMode.CLASSIC && hasListener) - chrome.commands.onCommand.removeListener(CommandHandler.onCommand); - else if (newMode == ChromeVoxMode.CLASSIC && !hasListener) - chrome.commands.onCommand.addListener(CommandHandler.onCommand); -}; - -/** * Increase or decrease a speech property and make an announcement. * @param {string} propertyName The name of the property to change. * @param {boolean} increase If true, increases the property value by one @@ -926,10 +914,62 @@ }; /** - * Performs global initialization. + * Provides a partial mapping from ChromeVox key combinations to + * Search-as-a-function key as seen in Chrome OS documentation. + * @param {cursors.Range} current + * @param {string} command + * @return {boolean} True if the command should propagate. * @private */ -CommandHandler.init_ = function() { +CommandHandler.onEditCommand_ = function(current, command) { + if (cvox.ChromeVox.isStickyModeOn() || !current || !current.start || + !current.start.node || !current.start.node.state[StateType.EDITABLE]) + return true; + + switch (command) { + case 'previousCharacter': + BackgroundKeyboardHandler.sendKeyPress(36, 'Home', Mod.SHIFT); + break; + case 'nextCharacter': + BackgroundKeyboardHandler.sendKeyPress(35, 'End', Mod.SHIFT); + break; + case 'previousWord': + BackgroundKeyboardHandler.sendKeyPress( + 36, 'Home', Mod.SHIFT | Mod.CONTROL); + break; + case 'nextWord': + BackgroundKeyboardHandler.sendKeyPress( + 35, 'End', Mod.SHIFT | Mod.CONTROL); + break; + case 'previousObject': + BackgroundKeyboardHandler.sendKeyPress(36, 'Home'); + break; + case 'nextObject': + BackgroundKeyboardHandler.sendKeyPress(35, 'End'); + break; + case 'previousLine': + BackgroundKeyboardHandler.sendKeyPress(33, 'PageUp'); + break; + case 'nextLine': + BackgroundKeyboardHandler.sendKeyPress(34, 'PageDown'); + break; + case 'jumpToTop': + BackgroundKeyboardHandler.sendKeyPress(36, 'Home', Mod.CONTROL); + break; + case 'jumpToBottom': + BackgroundKeyboardHandler.sendKeyPress(35, 'End', Mod.CONTROL); + break; + default: + return true; + } + return false; +}; + +/** + * Performs global initialization. + */ +CommandHandler.init = function() { + cvox.ChromeVoxKbHandler.commandHandler = CommandHandler.onCommand; var firstRunId = 'jdgcneonijmofocbhmijhacgchbihela'; chrome.runtime.onMessageExternal.addListener(function( request, sender, sendResponse) { @@ -955,6 +995,4 @@ }); }; -CommandHandler.init_(); - }); // goog.scope
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/constants.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/constants.js index 2fac773..762ca88e 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/constants.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/constants.js
@@ -30,3 +30,14 @@ * @const */ constants.OBJECT_MAX_CHARCOUNT = 1500; + +/** + * Modifier values used by Chrome. + * See ui/events/event_constants.h + */ +constants.ModifierFlag = { + SHIFT: 2, + CONTROL: 4, + ALT: 8, + SEARCH: 16 +};
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js index b31c9d0..37411cf 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/desktop_automation_handler.js
@@ -81,9 +81,6 @@ AutomationObjectConstructorInstaller.init(node, function() { chrome.automation.getFocus( (function(focus) { - if (ChromeVoxState.instance.mode != ChromeVoxMode.FORCE_NEXT) - return; - if (focus) { var event = new CustomAutomationEvent(EventType.FOCUS, focus, 'page'); @@ -137,9 +134,6 @@ ChromeVoxState.instance.setCurrentRange(cursors.Range.fromNode(node)); - if (!this.shouldOutput_(evt)) - return; - // Don't output if focused node hasn't changed. if (prevRange && evt.type == 'focus' && ChromeVoxState.instance.currentRange.equals(prevRange)) @@ -162,9 +156,6 @@ * @param {!AutomationEvent} evt */ onEventIfInRange: function(evt) { - if (!this.shouldOutput_(evt)) - return; - var prev = ChromeVoxState.instance.currentRange; if (prev.contentEquals(cursors.Range.fromNode(evt.target)) || evt.target.state.focused) { @@ -245,9 +236,6 @@ */ onAlert: function(evt) { var node = evt.target; - if (!node || !this.shouldOutput_(evt)) - return; - var range = cursors.Range.fromNode(node); new Output().withSpeechAndBraille(range, null, evt.type).go(); @@ -279,9 +267,6 @@ * @param {!AutomationEvent} evt */ onChildrenChanged: function(evt) { - if (!this.shouldOutput_(evt)) - return; - var curRange = ChromeVoxState.instance.currentRange; // Always refresh the braille contents. @@ -300,7 +285,8 @@ */ onFocus: function(evt) { if (evt.target.role == RoleType.ROOT_WEB_AREA) { - this.maybeRecoverFocusAndOutput_(evt); + chrome.automation.getFocus( + this.maybeRecoverFocusAndOutput_.bind(this, evt)); return; } @@ -335,9 +321,20 @@ onLoadComplete: function(evt) { this.lastRootUrl_ = ''; chrome.automation.getFocus(function(focus) { - if (!focus || !AutomationUtil.isDescendantOf(focus, evt.target)) + // In some situations, ancestor windows get focused before a descendant + // webView/rootWebArea. In particular, a window that gets opened but no + // inner focus gets set. We catch this generically by re-targetting focus + // if focus is the ancestor of the load complete target (below). + var focusIsAncestor = AutomationUtil.isDescendantOf(evt.target, focus); + var focusIsDescendant = AutomationUtil.isDescendantOf(focus, evt.target); + if (!focus || (!focusIsAncestor && !focusIsDescendant)) return; + if (focusIsAncestor) { + focus = evt.target; + Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); + } + // Create text edit handler, if needed, now in order not to miss initial // value change if text field has already been focused when initializing // ChromeVox. @@ -354,7 +351,7 @@ return; } - this.maybeRecoverFocusAndOutput_(evt); + this.maybeRecoverFocusAndOutput_(evt, focus); }.bind(this)); }, @@ -418,9 +415,6 @@ return; } - if (!this.shouldOutput_(evt)) - return; - var t = evt.target; var fromDesktop = t.root.role == RoleType.DESKTOP; if (t.state.focused || fromDesktop || @@ -454,7 +448,7 @@ */ onScrollPositionChanged: function(evt) { var currentRange = ChromeVoxState.instance.currentRange; - if (currentRange && currentRange.isValid() && this.shouldOutput_(evt)) + if (currentRange && currentRange.isValid()) new Output().withLocation(currentRange, null, evt.type).go(); }, @@ -559,66 +553,49 @@ }, /** - * Once an event handler updates ChromeVox's range based on |evt| - * which updates mode, returns whether |evt| should be outputted. - * @return {boolean} - */ - shouldOutput_: function(evt) { - var mode = ChromeVoxState.instance.mode; - // Only output desktop rooted nodes or web nodes for next engine modes. - return evt.target.root.role == RoleType.DESKTOP || - (mode == ChromeVoxMode.NEXT || mode == ChromeVoxMode.FORCE_NEXT || - mode == ChromeVoxMode.CLASSIC_COMPAT); - }, - - /** * @param {AutomationEvent} evt * @private */ - maybeRecoverFocusAndOutput_: function(evt) { - chrome.automation.getFocus(function(focus) { - var focusedRoot = AutomationUtil.getTopLevelRoot(focus); - if (!focusedRoot) - return; + maybeRecoverFocusAndOutput_: function(evt, focus) { + var focusedRoot = AutomationUtil.getTopLevelRoot(focus); + if (!focusedRoot) + return; - var curRoot; - if (ChromeVoxState.instance.currentRange) { - curRoot = AutomationUtil.getTopLevelRoot( - ChromeVoxState.instance.currentRange.start.node); - } + var curRoot; + if (ChromeVoxState.instance.currentRange) { + curRoot = AutomationUtil.getTopLevelRoot( + ChromeVoxState.instance.currentRange.start.node); + } - // If initial focus was already placed inside this page (e.g. if a user - // starts tabbing before load complete), then don't move ChromeVox's - // position on the page. - if (curRoot && focusedRoot == curRoot && - this.lastRootUrl_ == focusedRoot.docUrl) - return; + // If initial focus was already placed inside this page (e.g. if a user + // starts tabbing before load complete), then don't move ChromeVox's + // position on the page. + if (curRoot && focusedRoot == curRoot && + this.lastRootUrl_ == focusedRoot.docUrl) + return; - this.lastRootUrl_ = focusedRoot.docUrl || ''; - var o = new Output(); - // Restore to previous position. - var url = focusedRoot.docUrl; - url = url.substring(0, url.indexOf('#')) || url; - var pos = cvox.ChromeVox.position[url]; - if (pos) { - focus = AutomationUtil.hitTest(focusedRoot, pos) || focus; - if (focus != focusedRoot) - o.format('$name', focusedRoot); - } else { - // This catches initial focus (i.e. on startup). - if (!curRoot && focus != focusedRoot) - o.format('$name', focusedRoot); - } + this.lastRootUrl_ = focusedRoot.docUrl || ''; + var o = new Output(); + // Restore to previous position. + var url = focusedRoot.docUrl; + url = url.substring(0, url.indexOf('#')) || url; + var pos = cvox.ChromeVox.position[url]; + if (pos) { + focus = AutomationUtil.hitTest(focusedRoot, pos) || focus; + if (focus != focusedRoot) + o.format('$name', focusedRoot); + } else { + // This catches initial focus (i.e. on startup). + if (!curRoot && focus != focusedRoot) + o.format('$name', focusedRoot); + } - ChromeVoxState.instance.setCurrentRange(cursors.Range.fromNode(focus)); - if (!this.shouldOutput_(evt)) - return; + ChromeVoxState.instance.setCurrentRange(cursors.Range.fromNode(focus)); - Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); - o.withRichSpeechAndBraille( - ChromeVoxState.instance.currentRange, null, evt.type) - .go(); - }.bind(this)); + Output.forceModeForNextSpeechUtterance(cvox.QueueMode.FLUSH); + o.withRichSpeechAndBraille( + ChromeVoxState.instance.currentRange, null, evt.type) + .go(); } };
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/find_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/find_handler.js index b604b41..56537339 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/find_handler.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/find_handler.js
@@ -12,23 +12,9 @@ var TreeChangeObserverFilter = chrome.automation.TreeChangeObserverFilter; /** - * Responds to mode changes. - * @param {ChromeVoxMode} newMode - * @param {?ChromeVoxMode} oldMode Can be null at startup when no range was - * previously set. - */ -FindHandler.onModeChanged = function(newMode, oldMode) { - if (newMode == ChromeVoxMode.FORCE_NEXT) - FindHandler.init_(); - else - FindHandler.uninit_(); -}; - -/** * Initializes this module. - * @private */ -FindHandler.init_ = function() { +FindHandler.init = function() { chrome.automation.addTreeChangeObserver( TreeChangeObserverFilter.TEXT_MARKER_CHANGES, FindHandler.onTextMatch_); };
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/keyboard_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/keyboard_handler.js index 993fc81..636e087 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/keyboard_handler.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/keyboard_handler.js
@@ -8,13 +8,13 @@ goog.provide('BackgroundKeyboardHandler'); +goog.require('ChromeVoxState'); +goog.require('Output'); goog.require('cvox.ChromeVoxKbHandler'); +goog.require('cvox.ChromeVoxPrefs'); /** @constructor */ BackgroundKeyboardHandler = function() { - // Classic keymap. - cvox.ChromeVoxKbHandler.handlerKeyMap = cvox.KeyMap.fromDefaults(); - /** @type {number} @private */ this.passThroughKeyUpCount_ = 0; @@ -24,7 +24,9 @@ document.addEventListener('keydown', this.onKeyDown.bind(this), false); document.addEventListener('keyup', this.onKeyUp.bind(this), false); - chrome.accessibilityPrivate.setKeyboardListener(true, false); + chrome.accessibilityPrivate.setKeyboardListener( + true, cvox.ChromeVox.isStickyPrefOn); + window['prefs'].switchToKeyMap('keymap_next'); }; BackgroundKeyboardHandler.prototype = { @@ -38,8 +40,7 @@ if (cvox.ChromeVox.passThroughMode) return false; - if (ChromeVoxState.instance.mode != ChromeVoxMode.CLASSIC && - !cvox.ChromeVoxKbHandler.basicKeyDownActionsListener(evt)) { + if (cvox.ChromeVoxKbHandler.basicKeyDownActionsListener(evt)) { evt.preventDefault(); evt.stopPropagation(); this.eatenKeyDowns_.add(evt.keyCode); @@ -72,32 +73,26 @@ } return false; - }, - - /** - * React to mode changes. - * @param {ChromeVoxMode} newMode - * @param {ChromeVoxMode?} oldMode - */ - onModeChanged: function(newMode, oldMode) { - if (newMode == ChromeVoxMode.CLASSIC) { - chrome.accessibilityPrivate.setKeyboardListener(false, false); - } else { - chrome.accessibilityPrivate.setKeyboardListener( - true, cvox.ChromeVox.isStickyPrefOn); - } - - if (newMode === ChromeVoxMode.NEXT || - newMode === ChromeVoxMode.FORCE_NEXT) { - // Switching out of classic, classic compat, or uninitialized - // (on startup). - window['prefs'].switchToKeyMap('keymap_next'); - } else if ( - oldMode && oldMode != ChromeVoxMode.CLASSIC && - oldMode != ChromeVoxMode.CLASSIC_COMPAT) { - // Switching out of next. Intentionally do nothing when switching out of - // an uninitialized |oldMode|. - window['prefs'].switchToKeyMap('keymap_classic'); - } } }; + +/** + * @param {number} keyCode + * @param {string} keyName + * @param {number=} modifiers + * @return {boolean} + */ +BackgroundKeyboardHandler.sendKeyPress = function(keyCode, keyName, modifiers) { + modifiers = modifiers || 0; + var key = { + type: 'keydown', + keyCode: keyCode, + keyName: keyName, + charValue: keyCode, + modifiers: modifiers + }; + chrome.virtualKeyboardPrivate.sendKeyEvent(key); + key['type'] = 'keyup'; + chrome.virtualKeyboardPrivate.sendKeyEvent(key); + return true; +};
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/live_regions.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/live_regions.js index 3cdefdf..3f5b560e 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/live_regions.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/live_regions.js
@@ -84,7 +84,7 @@ var mode = this.chromeVoxState_.mode; var currentRange = this.chromeVoxState_.currentRange; - if (mode === ChromeVoxMode.CLASSIC || !cvox.ChromeVox.isActive) + if (!cvox.ChromeVox.isActive) return; if (!currentRange)
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/tabs_automation_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/tabs_automation_handler.js deleted file mode 100644 index 5a8512a..0000000 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/tabs_automation_handler.js +++ /dev/null
@@ -1,55 +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. - -/** - * @fileoverview Handles automation from a tabs automation node. - */ - -goog.provide('TabsAutomationHandler'); - -goog.require('CustomAutomationEvent'); -goog.require('DesktopAutomationHandler'); - -goog.scope(function() { -var EventType = chrome.automation.EventType; -var RoleType = chrome.automation.RoleType; -var StateType = chrome.automation.StateType; - -/** - * @param {!chrome.automation.AutomationNode} tabRoot - * @constructor - * @extends {DesktopAutomationHandler} - */ -TabsAutomationHandler = function(tabRoot) { - DesktopAutomationHandler.call(this, tabRoot); - - if (tabRoot.role != RoleType.ROOT_WEB_AREA) - throw new Error('Expected rootWebArea node but got ' + tabRoot.role); - - // When the root is focused, simulate what happens on a load complete. - if (tabRoot.state[StateType.FOCUSED]) { - var event = - new CustomAutomationEvent(EventType.LOAD_COMPLETE, tabRoot, 'page'); - this.onLoadComplete(event); - } -}; - -TabsAutomationHandler.prototype = { - __proto__: DesktopAutomationHandler.prototype, - - /** @override */ - didHandleEvent_: function(evt) { - evt.stopPropagation(); - }, - - /** @override */ - onLoadComplete: function(evt) { - var focused = evt.target.find({state: {focused: true}}) || evt.target; - var event = - new CustomAutomationEvent(EventType.FOCUS, focused, evt.eventFrom); - this.onFocus(event); - } -}; - -}); // goog.scope
diff --git a/chrome/browser/resources/chromeos/chromevox/testing/chromevox_e2e_test_base.js b/chrome/browser/resources/chromeos/chromevox/testing/chromevox_e2e_test_base.js index 6b03067..0b634d9f 100644 --- a/chrome/browser/resources/chromeos/chromevox/testing/chromevox_e2e_test_base.js +++ b/chrome/browser/resources/chromeos/chromevox/testing/chromevox_e2e_test_base.js
@@ -34,16 +34,20 @@ testGenCppIncludes: function() { GEN_BLOCK(function() { /*! #include "ash/accessibility/accessibility_delegate.h" +#include "ash/shell.h" #include "base/bind.h" #include "base/callback.h" #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/common/extensions/extension_constants.h" +#include "ui/keyboard/keyboard_util.h" */ }); }, /** @override */ testGenPreamble: function() { GEN_BLOCK(function() { /*! + keyboard::SetRequestedKeyboardState(keyboard::KEYBOARD_STATE_ENABLED); + ash::Shell::Get()->CreateKeyboard(); base::Closure load_cb = base::Bind(&chromeos::AccessibilityManager::EnableSpokenFeedback, base::Unretained(chromeos::AccessibilityManager::Get()),
diff --git a/chrome/browser/resources/md_extensions/detail_view.html b/chrome/browser/resources/md_extensions/detail_view.html index ab06307..4b8b86b 100644 --- a/chrome/browser/resources/md_extensions/detail_view.html +++ b/chrome/browser/resources/md_extensions/detail_view.html
@@ -14,6 +14,7 @@ <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/shadow.html"> <link rel="import" href="item_behavior.html"> @@ -178,6 +179,15 @@ #load-path > a[is='action-link'] { display: inline; } + + #size { + display: flex; + align-items: center; + } + + paper-spinner-lite { + @apply(--cr-icon-height-width); + } </style> <div id="container"> <div id="main"> @@ -265,6 +275,14 @@ <div class="section-title">$i18n{itemVersion}</div> <div class="section-content">[[data.version]]</div> </div> + <div class="section block"> + <div class="section-title">$i18n{itemSize}</div> + <div class="section-content" id="size"> + <span>[[size_]]</span> + <paper-spinner-lite active="[[!size_]]" hidden="[[size_]]"> + </paper-spinner-lite> + </div> + </div> <div class="section block" id="id-section" hidden$="[[!inDevMode]]"> <div class="section-title">$i18n{itemIdHeading}</div> <div class="section-content">[[data.id]]</div> @@ -357,13 +375,12 @@ </template> </div> </template> - <div class="section control-line actionable" id="extensions-options" - on-tap="onOptionsTap_" - hidden$="[[!shouldShowOptionsLink_(data.*)]]"> - <span id="optionLabel">$i18n{itemOptions}</span> - <button class="icon-external" is="paper-icon-button-light" - aria-labelledby="optionLabel" actionable></button> - </div> + <button class="hr" is="cr-link-row" id="extensions-options" + disabled="[[!isEnabled_(data.state)]]" + hidden="[[!shouldShowOptionsLink_(data.*)]]" + icon-class="icon-external" label="$i18n{itemOptions}" + on-tap="onExtensionOptionsTap_"> + </button> <button class="hr" hidden="[[!data.manifestHomePageUrl.length]]" is="cr-link-row" icon-class="icon-external" id="developerWebsite" label="$i18n{developerWebsite}" on-tap="onDeveloperWebSiteTap_">
diff --git a/chrome/browser/resources/md_extensions/detail_view.js b/chrome/browser/resources/md_extensions/detail_view.js index 96b31bd..424f445 100644 --- a/chrome/browser/resources/md_extensions/detail_view.js +++ b/chrome/browser/resources/md_extensions/detail_view.js
@@ -20,6 +20,9 @@ */ data: Object, + /** @private */ + size_: String, + /** @type {!extensions.ItemDelegate} */ delegate: Object, @@ -27,6 +30,20 @@ inDevMode: Boolean, }, + observers: [ + 'onItemIdChanged_(data.id, delegate)', + ], + + /** @private */ + onItemIdChanged_: function() { + // Clear the size, since this view is reused, such that no obsolete size + // is displayed.: + this.size_ = ''; + this.delegate.getExtensionSize(this.data.id).then(size => { + this.size_ = size; + }); + }, + /** * @param {string} description * @param {string} fallback @@ -146,7 +163,7 @@ }, /** @private */ - onOptionsTap_: function() { + onExtensionOptionsTap_: function() { this.delegate.showItemOptionsPage(this.data); },
diff --git a/chrome/browser/resources/md_extensions/item.js b/chrome/browser/resources/md_extensions/item.js index d9a1546..f2fb984 100644 --- a/chrome/browser/resources/md_extensions/item.js +++ b/chrome/browser/resources/md_extensions/item.js
@@ -63,6 +63,12 @@ /** @param {string} id */ showInFolder(id) {} + + /** + * @param {string} id + * @return {!Promise<string>} + */ + getExtensionSize(id) {} } const Item = Polymer({
diff --git a/chrome/browser/resources/md_extensions/pack_dialog.html b/chrome/browser/resources/md_extensions/pack_dialog.html index 2e11adbd..ac6a453d 100644 --- a/chrome/browser/resources/md_extensions/pack_dialog.html +++ b/chrome/browser/resources/md_extensions/pack_dialog.html
@@ -61,7 +61,7 @@ </dialog> <template is="dom-if" if="[[lastResponse_]]" restamp> <extensions-pack-dialog-alert model="[[lastResponse_]]" - on-warning-confirmed="onWarningConfirmed_" on-close="resetResponse_"> + on-close="onAlertClose_"> </extensions-pack-dialog-alert> </template> </template>
diff --git a/chrome/browser/resources/md_extensions/pack_dialog.js b/chrome/browser/resources/md_extensions/pack_dialog.js index de6f9b3..da4c849e 100644 --- a/chrome/browser/resources/md_extensions/pack_dialog.js +++ b/chrome/browser/resources/md_extensions/pack_dialog.js
@@ -89,25 +89,33 @@ * @private */ onPackResponse_: function(response) { - if (response.status === chrome.developerPrivate.PackStatus.SUCCESS) { - this.$.dialog.close(); - } else { - this.set('lastResponse_', response); - } + this.lastResponse_ = response; }, /** - * The handler function when user chooses to 'Proceed Anyway' upon - * receiving a waring. + * In the case that the alert dialog was a success message, the entire + * pack-dialog should close. Otherwise, we detach the alert by setting + * lastResponse_ null. Additionally, if the user selected "proceed anyway" + * in the dialog, we pack the extension again with override flags. + * @param {!Event} e * @private */ - onWarningConfirmed_: function() { - this.delegate.packExtension( - this.lastResponse_.item_path, this.lastResponse_.pem_path, - this.lastResponse_.override_flags, this.onPackResponse_.bind(this)); - }, + onAlertClose_: function(e) { + e.stopPropagation(); - resetResponse_: function() { + if (this.lastResponse_.status == + chrome.developerPrivate.PackStatus.SUCCESS) { + this.$.dialog.close(); + return; + } + + // This is only possible for a warning dialog. + if (this.$$('extensions-pack-dialog-alert').returnValue == 'success') { + this.delegate.packExtension( + this.lastResponse_.item_path, this.lastResponse_.pem_path, + this.lastResponse_.override_flags, this.onPackResponse_.bind(this)); + } + this.lastResponse_ = null; }, });
diff --git a/chrome/browser/resources/md_extensions/pack_dialog_alert.html b/chrome/browser/resources/md_extensions/pack_dialog_alert.html index 11db084..68bc231 100644 --- a/chrome/browser/resources/md_extensions/pack_dialog_alert.html +++ b/chrome/browser/resources/md_extensions/pack_dialog_alert.html
@@ -10,16 +10,19 @@ <dom-module id="extensions-pack-dialog-alert"> <template> <style include="cr-shared-style paper-button-style"> + .body { + white-space: pre-wrap; + word-break: break-word; + } </style> <dialog is="cr-dialog" id="dialog" close-text="$i18n{close}"> <div class="title" slot="title">[[title_]]</div> - <div class="body" slot="body"> - [[model.message]] - </div> + <!-- No whitespace or new-lines allowed within the div.body tag. --> + <div class="body" slot="body">[[model.message]]</div> <div class="button-container" slot="button-container"> - <paper-button class="cancel-button" on-tap="onCancelTap_" - hidden="[[!cancelLabel_]]"> + <paper-button class$="[[getCancelButtonClass_(confirmLabel_)]]" + on-tap="onCancelTap_" hidden="[[!cancelLabel_]]"> [[cancelLabel_]] </paper-button> <paper-button class="action-button" on-tap="onConfirmTap_"
diff --git a/chrome/browser/resources/md_extensions/pack_dialog_alert.js b/chrome/browser/resources/md_extensions/pack_dialog_alert.js index 3afe8734..7c3e475 100644 --- a/chrome/browser/resources/md_extensions/pack_dialog_alert.js +++ b/chrome/browser/resources/md_extensions/pack_dialog_alert.js
@@ -20,8 +20,19 @@ /** @private */ cancelLabel_: String, - /** @private */ - confirmLabel_: String, + /** + * This needs to be initialized to trigger data-binding. + * @private + */ + confirmLabel_: { + type: String, + value: '', + } + }, + + /** @return {string} */ + get returnValue() { + return this.$.dialog.returnValue; }, /** @override */ @@ -41,8 +52,10 @@ this.title_ = loadTimeData.getString('packDialogErrorTitle'); this.cancelLabel_ = loadTimeData.getString('ok'); break; - // If status were success, this dialog should not be attached at all. case chrome.developerPrivate.PackStatus.SUCCESS: + this.title_ = loadTimeData.getString('packDialogTitle'); + this.cancelLabel_ = loadTimeData.getString('ok'); + break; default: assertNotReached(); return; @@ -54,6 +67,14 @@ this.$.dialog.showModal(); }, + /** + * @return {string} + * @private + */ + getCancelButtonClass_: function() { + return this.confirmLabel_ ? 'cancel-button' : 'action-button'; + }, + /** @private */ onCancelTap_: function() { this.$.dialog.cancel(); @@ -63,7 +84,6 @@ onConfirmTap_: function() { // The confirm button should only be available in WARNING state. assert(this.model.status === chrome.developerPrivate.PackStatus.WARNING); - this.fire('warning-confirmed'); this.$.dialog.close(); } });
diff --git a/chrome/browser/resources/md_extensions/service.js b/chrome/browser/resources/md_extensions/service.js index db23c63..ec97a7c 100644 --- a/chrome/browser/resources/md_extensions/service.js +++ b/chrome/browser/resources/md_extensions/service.js
@@ -39,6 +39,13 @@ }); } + /** @override */ + getExtensionSize(id) { + return new Promise(function(resolve, reject) { + chrome.developerPrivate.getExtensionSize(id, resolve); + }); + } + /** * Opens a file browser dialog for the user to select a file (or directory). * @param {chrome.developerPrivate.SelectType} selectType
diff --git a/chrome/browser/resources/print_preview/data/app_state.js b/chrome/browser/resources/print_preview/data/app_state.js index 7fbeaa53..211b382 100644 --- a/chrome/browser/resources/print_preview/data/app_state.js +++ b/chrome/browser/resources/print_preview/data/app_state.js
@@ -26,24 +26,6 @@ VENDOR_OPTIONS: 'vendorOptions' }; -/** - * Creates a |RecentDestination| to represent |destination| in the app - * state. - * @param {!print_preview.Destination} destination The destination to store. - * @return {!print_preview.RecentDestination} - */ -function makeRecentDestination(destination) { - return { - id: destination.id, - origin: destination.origin, - account: destination.account || '', - capabilities: destination.capabilities, - displayName: destination.displayName || '', - extensionId: destination.extensionId || '', - extensionName: destination.extensionName || '', - }; -} - cr.define('print_preview', function() { 'use strict'; class AppState extends cr.EventTarget { @@ -221,7 +203,8 @@ // Determine if this destination is already in the recent destinations, // and where in the array it is located. - const newDestination = makeRecentDestination(assert(destination)); + const newDestination = + print_preview.makeRecentDestination(assert(destination)); let indexFound = this.state_[print_preview.AppStateField.RECENT_DESTINATIONS] .findIndex(function(recent) {
diff --git a/chrome/browser/resources/print_preview/data/destination.js b/chrome/browser/resources/print_preview/data/destination.js index dd2db77..d86170d 100644 --- a/chrome/browser/resources/print_preview/data/destination.js +++ b/chrome/browser/resources/print_preview/data/destination.js
@@ -108,9 +108,38 @@ */ print_preview.Cdd; +/** + * @typedef {{id: string, + * origin: print_preview.DestinationOrigin, + * account: string, + * capabilities: ?print_preview.Cdd, + * displayName: string, + * extensionId: string, + * extensionName: string}} + */ +print_preview.RecentDestination; + cr.define('print_preview', function() { 'use strict'; + /** + * Creates a |RecentDestination| to represent |destination| in the app + * state. + * @param {!print_preview.Destination} destination The destination to store. + * @return {!print_preview.RecentDestination} + */ + function makeRecentDestination(destination) { + return { + id: destination.id, + origin: destination.origin, + account: destination.account || '', + capabilities: destination.capabilities, + displayName: destination.displayName || '', + extensionId: destination.extensionId || '', + extensionName: destination.extensionName || '', + }; + } + class Destination { /** * Print destination data object that holds data for both local and cloud @@ -599,5 +628,6 @@ // Export return { Destination: Destination, + makeRecentDestination: makeRecentDestination, }; });
diff --git a/chrome/browser/resources/print_preview/data/destination_store.js b/chrome/browser/resources/print_preview/data/destination_store.js index 298d845..aa204aa 100644 --- a/chrome/browser/resources/print_preview/data/destination_store.js +++ b/chrome/browser/resources/print_preview/data/destination_store.js
@@ -5,17 +5,6 @@ cr.exportPath('print_preview'); /** - * @typedef {{id: string, - * origin: print_preview.DestinationOrigin, - * account: string, - * capabilities: ?print_preview.Cdd, - * displayName: string, - * extensionId: string, - * extensionName: string}} - */ -print_preview.RecentDestination; - -/** * Printer search statuses used by the destination store. * @enum {string} */
diff --git a/chrome/browser/resources/print_preview/data/print_ticket_store.js b/chrome/browser/resources/print_preview/data/print_ticket_store.js index e03d5826..b1ad663 100644 --- a/chrome/browser/resources/print_preview/data/print_ticket_store.js +++ b/chrome/browser/resources/print_preview/data/print_ticket_store.js
@@ -435,7 +435,20 @@ cjt.print.color.vendor_id = selectedOption.vendor_id; } } + } else { + // Always try setting the color in the print ticket, otherwise a + // reasonable reader of the ticket will have to do more work, or process + // the ticket sub-optimally, in order to safely handle the lack of a + // color ticket item. + const defaultOption = this.color.defaultColorOption(); + if (defaultOption) { + cjt.print.color = {type: defaultOption.type}; + if (defaultOption.hasOwnProperty('vendor_id')) { + cjt.print.color.vendor_id = defaultOption.vendor_id; + } + } } + if (this.copies.isCapabilityAvailable() && this.copies.isUserEdited()) { cjt.print.copies = {copies: this.copies.getValueAsNumber()}; }
diff --git a/chrome/browser/resources/print_preview/data/ticket_items/color.js b/chrome/browser/resources/print_preview/data/ticket_items/color.js index 2df29ad..f5e0077 100644 --- a/chrome/browser/resources/print_preview/data/ticket_items/color.js +++ b/chrome/browser/resources/print_preview/data/ticket_items/color.js
@@ -49,6 +49,18 @@ null; } + /** @return {Object} Printer's default color option. */ + defaultColorOption() { + const capability = this.capability; + if (!capability) { + return null; + } + const defaultOptions = capability.option.filter(function(option) { + return option.is_default; + }); + return defaultOptions.length != 0 ? defaultOptions[0] : null; + } + /** @return {Object} Color option corresponding to the current value. */ getSelectedOption() { const capability = this.capability; @@ -70,9 +82,7 @@ /** @override */ getDefaultValueInternal() { - const capability = this.capability; - const defaultOption = - capability ? this.getDefaultColorOption_(capability.option) : null; + const defaultOption = this.defaultColorOption(); return defaultOption && (Color.COLOR_TYPES_.indexOf(defaultOption.type) >= 0); } @@ -91,21 +101,6 @@ } return this.getDefaultValueInternal(); } - - /** - * @param {!Array<!Object<{type: (string|undefined), - * is_default: (boolean|undefined)}>>} options - * @return {Object<{type: (string|undefined), - * is_default: (boolean|undefined)}>} Default color - * option of the given list. - * @private - */ - getDefaultColorOption_(options) { - const defaultOptions = options.filter(function(option) { - return option.is_default; - }); - return (defaultOptions.length == 0) ? null : defaultOptions[0]; - } } /**
diff --git a/chrome/browser/resources/print_preview/new/app.html b/chrome/browser/resources/print_preview/new/app.html index b0a27f3..dec14ae 100644 --- a/chrome/browser/resources/print_preview/new/app.html +++ b/chrome/browser/resources/print_preview/new/app.html
@@ -1,6 +1,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/html/cr.html"> +<link rel="import" href="chrome://resources/html/event_tracker.html"> <link rel="import" href="chrome://resources/html/webui_listener_tracker.html"> <link rel="import" href="../native_layer.html"> <link rel="import" href="../data/destination.html">
diff --git a/chrome/browser/resources/print_preview/new/app.js b/chrome/browser/resources/print_preview/new/app.js index bd8f963a..51b7153 100644 --- a/chrome/browser/resources/print_preview/new/app.js +++ b/chrome/browser/resources/print_preview/new/app.js
@@ -59,63 +59,6 @@ destination_: { type: Object, notify: true, - value: function() { - const dest = new print_preview.Destination( - 'Foo Printer', print_preview.DestinationType.LOCAL, - print_preview.DestinationOrigin.LOCAL, 'Foo Printer', true, - print_preview.DestinationConnectionStatus.ONLINE, - {description: 'PrinterBrandAA 12345'}); - dest.capabilities = { - version: '1.0', - printer: { - collate: {default: true}, - color: { - option: [ - {type: 'STANDARD_COLOR', is_default: true}, - {type: 'STANDARD_MONOCHROME'} - ] - }, - copies: {default: 1, max: 1000}, - dpi: { - option: [ - {horizontal_dpi: 200, vertical_dpi: 200, is_default: true}, - {horizontal_dpi: 100, vertical_dpi: 100}, - ] - }, - duplex: { - option: [ - {type: 'NO_DUPLEX', is_default: true}, {type: 'LONG_EDGE'}, - {type: 'SHORT_EDGE'} - ] - }, - page_orientation: { - option: [ - {type: 'PORTRAIT', is_default: true}, {type: 'LANDSCAPE'}, - {type: 'AUTO'} - ] - }, - media_size: { - option: [ - { - name: 'NA_LETTER', - width_microns: 215900, - height_microns: 279400, - is_default: true, - custom_display_name: 'Letter', - }, - { - name: 'CUSTOM_SQUARE', - width_microns: 215900, - height_microns: 215900, - custom_display_name: 'CUSTOM_SQUARE', - } - ] - }, - vendor_capability: [], - } - }; - return dest; - }, }, /** @private {!print_preview_new.State} */ @@ -132,6 +75,16 @@ }, }, + observers: [ + 'updateRecentDestinations_(destination_, destination_.capabilities)', + ], + + /** + * @private {number} Number of recent destinations to save. + * @const + */ + NUM_DESTINATIONS_: 3, + /** @private {?print_preview.NativeLayer} */ nativeLayer_: null, @@ -141,6 +94,12 @@ /** @private {?WebUIListenerTracker} */ listenerTracker_: null, + /** @private {?print_preview.DestinationStore} */ + destinationStore_: null, + + /** @private {!EventTracker} */ + tracker_: new EventTracker(), + /** @type {!print_preview.MeasurementSystem} */ measurementSystem_: new print_preview.MeasurementSystem( ',', '.', print_preview.MeasurementSystemUnitType.IMPERIAL), @@ -156,6 +115,15 @@ this.listenerTracker_ = new WebUIListenerTracker(); this.destinationStore_ = new print_preview.DestinationStore( this.userInfo_, this.listenerTracker_); + this.tracker_.add( + this.destinationStore_, + print_preview.DestinationStore.EventType.DESTINATION_SELECT, + this.onDestinationSelect_.bind(this)); + this.tracker_.add( + this.destinationStore_, + print_preview.DestinationStore.EventType + .SELECTED_DESTINATION_CAPABILITIES_READY, + this.onDestinationUpdated_.bind(this)); this.nativeLayer_.getInitialSettings().then( this.onInitialSettingsSet_.bind(this)); }, @@ -163,6 +131,7 @@ /** @override */ detached: function() { this.listenerTracker_.removeAll(); + this.tracker_.removeAll(); }, /** @@ -193,6 +162,53 @@ this.recentDestinations_); }, + /** @private */ + onDestinationSelect_: function() { + this.destination_ = this.destinationStore_.selectedDestination; + }, + + /** @private */ + onDestinationUpdated_: function() { + this.set( + 'destination_.capabilities', + this.destinationStore_.selectedDestination.capabilities); + }, + + /** @private */ + updateRecentDestinations_: function() { + if (!this.destination_) + return; + + // Determine if this destination is already in the recent destinations, + // and where in the array it is located. + const newDestination = + print_preview.makeRecentDestination(assert(this.destination_)); + let indexFound = this.recentDestinations_.findIndex(function(recent) { + return ( + newDestination.id == recent.id && + newDestination.origin == recent.origin); + }); + + // No change + if (indexFound == 0 && + this.recentDestinations_[0].capabilities == + newDestination.capabilities) { + return; + } + + // Shift the array so that the nth most recent destination is located at + // index n. + if (indexFound == -1 && + this.recentDestinations_.length == this.NUM_DESTINATIONS_) { + indexFound = this.NUM_DESTINATIONS_ - 1; + } + if (indexFound != -1) + this.recentDestinations_.splice(indexFound, 1); + + // Add the most recent destination + this.recentDestinations_.splice(0, 0, newDestination); + }, + /** * @param {?string} savedSettingsStr The sticky settings from native layer * @private
diff --git a/chrome/browser/resources/print_preview/new/compiled_resources2.gyp b/chrome/browser/resources/print_preview/new/compiled_resources2.gyp index 10e87fed..d12b908 100644 --- a/chrome/browser/resources/print_preview/new/compiled_resources2.gyp +++ b/chrome/browser/resources/print_preview/new/compiled_resources2.gyp
@@ -26,6 +26,8 @@ '../data/compiled_resources2.gyp:document_info', '../data/compiled_resources2.gyp:measurement_system', '../data/compiled_resources2.gyp:user_info', + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr', + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:event_tracker', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:webui_listener_tracker', ], 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
diff --git a/chrome/browser/resources/print_preview/new/destination_settings.html b/chrome/browser/resources/print_preview/new/destination_settings.html index d2882dde4..03eb8c37 100644 --- a/chrome/browser/resources/print_preview/new/destination_settings.html +++ b/chrome/browser/resources/print_preview/new/destination_settings.html
@@ -23,6 +23,7 @@ align-items: center; display: flex; min-height: 28px; + overflow: hidden; } .destination-icon { @@ -36,6 +37,7 @@ display: flex; flex: 1; flex-direction: column; + overflow: hidden; width: 100%; }
diff --git a/chrome/browser/resources/print_preview/new/model.js b/chrome/browser/resources/print_preview/new/model.js index bd6d31c6..5bd8ec7 100644 --- a/chrome/browser/resources/print_preview/new/model.js +++ b/chrome/browser/resources/print_preview/new/model.js
@@ -175,6 +175,7 @@ 'destination.id, destination.capabilities, ' + 'documentInfo.isModifiable, documentInfo.hasCssMediaStyles,' + 'documentInfo.hasSelection)'], + /** * @private {!Array<string>} List of capability types considered color. * @const
diff --git a/chrome/browser/resources/print_preview/new/settings_section.html b/chrome/browser/resources/print_preview/new/settings_section.html index be94c427..83083c4 100644 --- a/chrome/browser/resources/print_preview/new/settings_section.html +++ b/chrome/browser/resources/print_preview/new/settings_section.html
@@ -12,13 +12,15 @@ ::slotted([slot=controls]) { flex: 1; + overflow: hidden; } ::slotted([slot=title]) { -webkit-padding-end: 20px; color: #646464; font-size: 1em; - width: 70px; + max-width: 70px; + min-width: 70px; word-break: break-word; }
diff --git a/chrome/browser/resources/print_preview/print_preview.js b/chrome/browser/resources/print_preview/print_preview.js index 548fb1d..f7c0695 100644 --- a/chrome/browser/resources/print_preview/print_preview.js +++ b/chrome/browser/resources/print_preview/print_preview.js
@@ -561,39 +561,19 @@ } const destination = assert(this.destinationStore_.selectedDestination); const whenPrintDone = this.sendPrintRequest_(destination); - if (this.uiState_ == PrintPreviewUiState_.OPENING_PDF_PREVIEW || - (destination.isLocal && !destination.isPrivet && - !destination.isExtension && - destination.id != - print_preview.Destination.GooglePromotedId.SAVE_AS_PDF)) { - // Local printers resolve when print is ready to start. Hide the - // dialog. Mac "Open in Preview" is treated as a local printer. - const boundHideDialog = () => { - this.nativeLayer_.hidePreview(); - }; - whenPrintDone.then(boundHideDialog, boundHideDialog); - } else if (!destination.isLocal) { + if (destination.isLocal) { + const onError = destination.id == + print_preview.Destination.GooglePromotedId.SAVE_AS_PDF ? + this.onFileSelectionCancel_.bind(this) : + this.onPrintFailed_.bind(this); + whenPrintDone.then(this.close_.bind(this), onError); + } else { // Cloud print resolves when print data is returned to submit to cloud // print, or if print ticket cannot be read, no PDF data is found, or // PDF is oversized. whenPrintDone.then( this.onPrintToCloud_.bind(this), this.onPrintFailed_.bind(this)); - } else if (destination.isPrivet || destination.isExtension) { - // Privet and extension resolve when printing is complete or if there - // is an error printing. - whenPrintDone.then( - this.close_.bind(this, false), - this.onPrintFailed_.bind(this)); - } else { - assert( - destination.id == - print_preview.Destination.GooglePromotedId.SAVE_AS_PDF); - // Save as PDF resolves when file selection is completed or cancelled. - whenPrintDone.then( - this.close_.bind(this, false), - this.onFileSelectionCancel_.bind(this)); } - this.showSystemDialogBeforeNextPrint_ = false; return print_preview.PrintAttemptResult_.PRINTED; },
diff --git a/chrome/browser/resources/settings/internet_page/internet_page_browser_proxy.js b/chrome/browser/resources/settings/internet_page/internet_page_browser_proxy.js index 12e43de..a02946a 100644 --- a/chrome/browser/resources/settings/internet_page/internet_page_browser_proxy.js +++ b/chrome/browser/resources/settings/internet_page/internet_page_browser_proxy.js
@@ -42,6 +42,23 @@ * @param {function(?Array<settings.ArcVpnProvider>):void} callback */ setUpdateArcVpnProvidersCallback(callback) {} + + /** + * Requests that Chrome send the list of devices whose "Google Play + * Services" notifications are disabled (these notifications must be enabled + * to utilize Instant Tethering). The names will be provided via + * setGmsCoreNotificationsDisabledDeviceNamesCallback(). + */ + requestGmsCoreNotificationsDisabledDeviceNames() {} + + /** + * Sets the callback to be used to receive the list of devices whose "Google + * Play Services" notifications are disabled. |callback| is invoked with an + * array of the names of these devices; note that if no devices have this + * property, the provided list of device names is empty. + * @param {function(!Array<string>):void} callback + */ + setGmsCoreNotificationsDisabledDeviceNamesCallback(callback) {} } /** @@ -67,6 +84,17 @@ setUpdateArcVpnProvidersCallback(callback) { cr.addWebUIListener('sendArcVpnProviders', callback); } + + /** @override */ + requestGmsCoreNotificationsDisabledDeviceNames() { + chrome.send('requestGmsCoreNotificationsDisabledDeviceNames'); + } + + /** @override */ + setGmsCoreNotificationsDisabledDeviceNamesCallback(callback) { + cr.addWebUIListener( + 'sendGmsCoreNotificationsDisabledDeviceNames', callback); + } } cr.addSingletonGetter(InternetPageBrowserProxyImpl);
diff --git a/chrome/browser/resources/settings/internet_page/internet_subpage.html b/chrome/browser/resources/settings/internet_page/internet_subpage.html index 892b52e..3119ac4e 100644 --- a/chrome/browser/resources/settings/internet_page/internet_subpage.html +++ b/chrome/browser/resources/settings/internet_page/internet_subpage.html
@@ -12,13 +12,18 @@ <template> <style include="settings-shared iron-flex"> #networkListDiv { + margin-top: var(--settings-page-vertical-margin); + min-height: var(--settings-row-min-height); + } + + /* Set padding on children instead of the container itself to ensure that + separator lines can fill the entire width of the page. */ + #networkListDiv > * { /* cr-network-list is padded to the right to allow space for a ripple */ -webkit-padding-end: calc(var(--settings-box-row-padding) - var(--cr-icon-ripple-padding)); -webkit-padding-start: var(--settings-box-row-padding); - margin-top: var(--settings-page-vertical-margin); - min-height: var(--settings-row-min-height); - } + } #addButton { -webkit-margin-end: var(--settings-control-label-spacing); @@ -46,6 +51,29 @@ cr-network-list { flex: 1; } + + #gmscore-notifications-container { + border-top: var(--cr-separator-line); + margin: 10px 0; + padding-bottom: var(--cr-section-padding); + padding-top: var(--cr-section-padding); + } + + #gmscore-notifications-container[no-networks-text-below] { + border-bottom: var(--cr-separator-line); + margin-top: 0; + } + + #gmscore-notifications-device-string { + @apply(--cr-secondary-text); + margin-top: 5px; + } + + #gmscore-notifications-instructions { + @apply(--cr-secondary-text); + -webkit-padding-start: 15px; + margin: 0; + } </style> <template is="dom-if" if="[[enableToggleIsVisible_(deviceState)]]"> @@ -81,26 +109,53 @@ <template is="dom-if" if="[[deviceIsEnabled_(deviceState)]]"> <div id="networkListDiv" class="layout vertical flex"> <!-- VPN only header for built-in VPNs. --> - <div class="vpn-header layout horizontal center" - hidden$="[[!isEqual_('VPN', deviceState.Type)]]"> - <div class="flex">$i18n{networkVpnBuiltin}</div> - <button is="paper-icon-button-light" class="icon-add-circle" - aria-label="$i18n{internetAddVPN}" - on-tap="onAddButtonTap_" tabindex$="[[tabindex]]"> - </button> - </div> + <template is="dom-if" if="[[isEqual_('VPN', deviceState.Type)]]"> + <div class="vpn-header layout horizontal center"> + <div class="flex">$i18n{networkVpnBuiltin}</div> + <button is="paper-icon-button-light" class="icon-add-circle" + aria-label="$i18n{internetAddVPN}" + on-tap="onAddButtonTap_" tabindex$="[[tabindex]]"> + </button> + </div> + </template> - <!-- List of networks or 'None'. --> - <cr-network-list id="networkList" show-buttons - hidden$="[[!shouldShowNetworkList_(networkStateList_)]]" - networks="[[networkStateList_]]" - on-selected="onNetworkSelected_"> - </cr-network-list> - <div hidden$="[[shouldShowNetworkList_(networkStateList_)]]" - inner-h-t-m-l= - "[[getNoNetworksString_(deviceState, tetherDeviceState)]]" - class="no-networks"> - </div> + <!-- List of networks (empty if no networks exist). --> + <template is="dom-if" + if="[[shouldShowNetworkList_(networkStateList_)]]"> + <cr-network-list id="networkList" show-buttons + networks="[[networkStateList_]]" + on-selected="onNetworkSelected_"> + </cr-network-list> + </template> + + <!-- Instructions for how to enable "Google Play Services" notifications + (needed for Instant Tethering). --> + <template is="dom-if" if="[[showGmsCoreNotificationsSection_( + notificationsDisabledDeviceNames_)]]"> + <div id="gmscore-notifications-container" + no-networks-text-below$="[[!networkStateList_.length]]"> + <div>$i18n{gmscoreNotificationsTitle}</div> + <div id="gmscore-notifications-device-string"> + [[getGmsCoreNotificationsDevicesString_( + notificationsDisabledDeviceNames_)]] + </div> + <ol id="gmscore-notifications-instructions"> + <li>$i18n{gmscoreNotificationsFirstStep}</li> + <li>$i18n{gmscoreNotificationsSecondStep}</li> + <li>$i18n{gmscoreNotificationsThirdStep}</li> + </ol> + </div> + </template> + + <!-- Text shown if no networks exist. --> + <template is="dom-if" + if="[[!shouldShowNetworkList_(networkStateList_)]]"> + <div + inner-h-t-m-l= + "[[getNoNetworksString_(deviceState, tetherDeviceState)]]" + class="no-networks"> + </div> + </template> <template is="dom-if" if="[[isEqual_('VPN', deviceState.Type)]]"> <!-- Third party VPNs. -->
diff --git a/chrome/browser/resources/settings/internet_page/internet_subpage.js b/chrome/browser/resources/settings/internet_page/internet_subpage.js index 69592e2c..45ebfe6 100644 --- a/chrome/browser/resources/settings/internet_page/internet_subpage.js +++ b/chrome/browser/resources/settings/internet_page/internet_subpage.js
@@ -98,7 +98,19 @@ value: function() { return {}; } - } + }, + + /** + * List of potential Tether hosts whose "Google Play Services" notifications + * are disabled (these notifications are required to use Instant Tethering). + * @private {!Array<string>} + */ + notificationsDisabledDeviceNames_: { + type: Array, + value: function() { + return []; + }, + }, }, listeners: {'network-list-changed': 'getNetworkStateList_'}, @@ -116,6 +128,13 @@ this.browserProxy_ = settings.InternetPageBrowserProxyImpl.getInstance(); }, + /** @override */ + ready: function() { + this.browserProxy_.setGmsCoreNotificationsDisabledDeviceNamesCallback( + this.onNotificationsDisabledDeviceNamesReceived_.bind(this)); + this.browserProxy_.requestGmsCoreNotificationsDisabledDeviceNames(); + }, + /** override */ detached: function() { this.stopScanning_(); @@ -270,6 +289,15 @@ }, /** + * @param {!Array<string>} notificationsDisabledDeviceNames + * @private + */ + onNotificationsDisabledDeviceNamesReceived_: function( + notificationsDisabledDeviceNames) { + this.notificationsDisabledDeviceNames_ = notificationsDisabledDeviceNames; + }, + + /** * @param {!CrOnc.DeviceStateProperties|undefined} deviceState * @return {boolean} Whether or not the device state is enabled. * @private @@ -588,4 +616,36 @@ return this.i18n('internetNoNetworks'); }, + + /** + * @param {!Array<string>} notificationsDisabledDeviceNames + * @return {boolean} + * @private + */ + showGmsCoreNotificationsSection_: function(notificationsDisabledDeviceNames) { + return notificationsDisabledDeviceNames.length > 0; + }, + + /** + * @param {!Array<string>} notificationsDisabledDeviceNames + * @return {string} + * @private + */ + getGmsCoreNotificationsDevicesString_: function( + notificationsDisabledDeviceNames) { + if (notificationsDisabledDeviceNames.length == 1) { + return this.i18n( + 'gmscoreNotificationsOneDeviceSubtitle', + notificationsDisabledDeviceNames[0]); + } + + if (notificationsDisabledDeviceNames.length == 2) { + return this.i18n( + 'gmscoreNotificationsTwoDevicesSubtitle', + notificationsDisabledDeviceNames[0], + notificationsDisabledDeviceNames[1]); + } + + return this.i18n('gmscoreNotificationsManyDevicesSubtitle'); + }, });
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 2001a26..c538388d 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -805,6 +805,10 @@ "layout_constants.h", "location_bar/location_bar.cc", "location_bar/location_bar.h", + "media_router/presentation_receiver_window.h", + "media_router/presentation_receiver_window_controller.cc", + "media_router/presentation_receiver_window_controller.h", + "media_router/presentation_receiver_window_delegate.h", "native_window_tracker.h", "omnibox/alternate_nav_infobar_delegate.cc", "omnibox/alternate_nav_infobar_delegate.h", @@ -3041,6 +3045,11 @@ "views/location_bar/star_view.h", "views/location_bar/zoom_view.cc", "views/location_bar/zoom_view.h", + "views/media_router/presentation_receiver_window_factory.cc", + "views/media_router/presentation_receiver_window_frame.cc", + "views/media_router/presentation_receiver_window_frame.h", + "views/media_router/presentation_receiver_window_view.cc", + "views/media_router/presentation_receiver_window_view.h", "views/omnibox/omnibox_popup_contents_view.cc", "views/omnibox/omnibox_popup_contents_view.h", "views/omnibox/omnibox_result_view.cc",
diff --git a/chrome/browser/ui/ash/chrome_keyboard_ui.cc b/chrome/browser/ui/ash/chrome_keyboard_ui.cc index ef053f4..d37dda46b 100644 --- a/chrome/browser/ui/ash/chrome_keyboard_ui.cc +++ b/chrome/browser/ui/ash/chrome_keyboard_ui.cc
@@ -45,6 +45,7 @@ #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/gfx/geometry/insets.h" #include "ui/keyboard/content/keyboard_constants.h" +#include "ui/keyboard/content/keyboard_content_util.h" #include "ui/keyboard/keyboard_controller.h" #include "ui/keyboard/keyboard_controller_observer.h" #include "ui/keyboard/keyboard_switches.h"
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc index 9017d62..ae2a788 100644 --- a/chrome/browser/ui/ash/chrome_shell_delegate.cc +++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -66,8 +66,6 @@ #include "content/public/common/url_constants.h" #include "services/ui/public/cpp/input_devices/input_device_controller_client.h" #include "ui/aura/window.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" #include "url/url_constants.h" using chromeos::AccessibilityManager; @@ -356,10 +354,6 @@ displayer.browser()->window()->GetNativeWindow()); } -base::string16 ChromeShellDelegate::GetProductName() const { - return l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); -} - void ChromeShellDelegate::OpenKeyboardShortcutHelpPage() const { Profile* profile = ProfileManager::GetActiveUserProfile(); Browser* browser = chrome::FindTabbedBrowser(profile, false);
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.h b/chrome/browser/ui/ash/chrome_shell_delegate.h index 9241c54..76572659 100644 --- a/chrome/browser/ui/ash/chrome_shell_delegate.h +++ b/chrome/browser/ui/ash/chrome_shell_delegate.h
@@ -41,7 +41,6 @@ std::unique_ptr<ash::ScreenshotDelegate> CreateScreenshotDelegate() override; std::unique_ptr<ash::WallpaperDelegate> CreateWallpaperDelegate() override; ash::AccessibilityDelegate* CreateAccessibilityDelegate() override; - base::string16 GetProductName() const override; void OpenKeyboardShortcutHelpPage() const override; ui::InputDeviceControllerClient* GetInputDeviceControllerClient() override;
diff --git a/chrome/browser/ui/ash/keyboard_controller_browsertest.cc b/chrome/browser/ui/ash/keyboard_controller_browsertest.cc index f7110b9..70d6fb2 100644 --- a/chrome/browser/ui/ash/keyboard_controller_browsertest.cc +++ b/chrome/browser/ui/ash/keyboard_controller_browsertest.cc
@@ -19,11 +19,11 @@ #include "ui/base/ime/input_method.h" #include "ui/base/ime/input_method_factory.h" #include "ui/keyboard/content/keyboard_constants.h" +#include "ui/keyboard/content/keyboard_content_util.h" #include "ui/keyboard/keyboard_controller.h" #include "ui/keyboard/keyboard_switches.h" #include "ui/keyboard/keyboard_test_util.h" #include "ui/keyboard/keyboard_ui.h" -#include "ui/keyboard/keyboard_util.h" namespace { const int kKeyboardHeightForTest = 100;
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 34dfc31..5bec651 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -50,7 +50,6 @@ #include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/download/download_core_service.h" #include "chrome/browser/download/download_core_service_factory.h" -#include "chrome/browser/extensions/api/tab_capture/offscreen_tab.h" #include "chrome/browser/extensions/api/tabs/tabs_event_router.h" #include "chrome/browser/extensions/api/tabs/tabs_windows_api.h" #include "chrome/browser/extensions/browser_extension_window_controller.h" @@ -535,13 +534,14 @@ // because the ProfileManager needs to be able to destroy all profiles when // it is destroyed. See crbug.com/527035 // - // A profile used to render an offscreen tab should not be destroyed while - // that tab is still alive. The offscreen tab is not associated with a - // browser (similar to the user manager window case). See crbug.com/664351 + // A profile created with Profile::CreateOffTheRecordProfile() should not be + // destroyed directly by Browser (e.g. for offscreen tabs, + // https://crbug.com/664351). if (profile_->IsOffTheRecord() && + profile_->GetOriginalProfile()->HasOffTheRecordProfile() && + profile_->GetOriginalProfile()->GetOffTheRecordProfile() == profile_ && !BrowserList::IsIncognitoSessionActiveForProfile(profile_) && - !profile_->GetOriginalProfile()->IsSystemProfile() && - !extensions::OffscreenTabsOwner::IsOffscreenProfile(profile_)) { + !profile_->GetOriginalProfile()->IsSystemProfile()) { if (profile_->IsGuestSession()) { // ChromeOS handles guest data independently. #if !defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc index c3e655a..b8e1c65 100644 --- a/chrome/browser/ui/browser_browsertest.cc +++ b/chrome/browser/ui/browser_browsertest.cc
@@ -1400,8 +1400,7 @@ GetController())); chrome::GoBack(browser(), WindowOpenDisposition::CURRENT_TAB); back_nav_load_observer.Wait(); - CommandUpdater* command_updater = - browser()->command_controller()->command_updater(); + CommandUpdater* command_updater = browser()->command_controller(); EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_FORWARD)); content::WindowedNotificationObserver forward_nav_load_observer( @@ -1418,8 +1417,7 @@ // Makes sure certain commands are disabled when Incognito mode is forced. IN_PROC_BROWSER_TEST_F(BrowserTest, DisableMenuItemsWhenIncognitoIsForced) { - CommandUpdater* command_updater = - browser()->command_controller()->command_updater(); + CommandUpdater* command_updater = browser()->command_controller(); // At the beginning, all commands are enabled. EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_NEW_WINDOW)); EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_NEW_INCOGNITO_WINDOW)); @@ -1443,8 +1441,7 @@ // Create a new browser. Browser* new_browser = new Browser(Browser::CreateParams( browser()->profile()->GetOffTheRecordProfile(), true)); - CommandUpdater* new_command_updater = - new_browser->command_controller()->command_updater(); + CommandUpdater* new_command_updater = new_browser->command_controller(); // It should have Bookmarks & Settings commands disabled by default. EXPECT_FALSE(new_command_updater->IsCommandEnabled(IDC_NEW_WINDOW)); EXPECT_FALSE(new_command_updater->IsCommandEnabled( @@ -1459,8 +1456,7 @@ // not available. IN_PROC_BROWSER_TEST_F(BrowserTest, NoNewIncognitoWindowWhenIncognitoIsDisabled) { - CommandUpdater* command_updater = - browser()->command_controller()->command_updater(); + CommandUpdater* command_updater = browser()->command_controller(); // Set Incognito to DISABLED. IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(), IncognitoModePrefs::DISABLED); @@ -1476,8 +1472,7 @@ // Create a new browser. Browser* new_browser = new Browser(Browser::CreateParams(browser()->profile(), true)); - CommandUpdater* new_command_updater = - new_browser->command_controller()->command_updater(); + CommandUpdater* new_command_updater = new_browser->command_controller(); EXPECT_FALSE(new_command_updater->IsCommandEnabled(IDC_NEW_INCOGNITO_WINDOW)); EXPECT_TRUE(new_command_updater->IsCommandEnabled(IDC_NEW_WINDOW)); EXPECT_TRUE(new_command_updater->IsCommandEnabled(IDC_SHOW_BOOKMARK_MANAGER)); @@ -1504,8 +1499,7 @@ // circumstances even though normally they should stay enabled. IN_PROC_BROWSER_TEST_F(BrowserTestWithExtensionsDisabled, DisableExtensionsAndSettingsWhenIncognitoIsDisabled) { - CommandUpdater* command_updater = - browser()->command_controller()->command_updater(); + CommandUpdater* command_updater = browser()->command_controller(); // Set Incognito to DISABLED. IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(), IncognitoModePrefs::DISABLED); @@ -1520,8 +1514,7 @@ // as Extensions should be disabled. Browser* popup_browser = new Browser( Browser::CreateParams(Browser::TYPE_POPUP, browser()->profile(), true)); - CommandUpdater* popup_command_updater = - popup_browser->command_controller()->command_updater(); + CommandUpdater* popup_command_updater = popup_browser->command_controller(); EXPECT_FALSE(popup_command_updater->IsCommandEnabled(IDC_MANAGE_EXTENSIONS)); EXPECT_FALSE(popup_command_updater->IsCommandEnabled(IDC_OPTIONS)); EXPECT_TRUE(popup_command_updater->IsCommandEnabled( @@ -1536,8 +1529,7 @@ // Create a popup browser. Browser* popup_browser = new Browser( Browser::CreateParams(Browser::TYPE_POPUP, browser()->profile(), true)); - CommandUpdater* command_updater = - popup_browser->command_controller()->command_updater(); + CommandUpdater* command_updater = popup_browser->command_controller(); // OPTIONS and IMPORT_SETTINGS are disabled for a non-normal UI. EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_OPTIONS)); EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_IMPORT_SETTINGS)); @@ -1647,8 +1639,7 @@ GURL url(embedded_test_server()->GetURL("/empty.html")); ui_test_utils::NavigateToURL(browser(), url); - CommandUpdater* command_updater = - browser()->command_controller()->command_updater(); + CommandUpdater* command_updater = browser()->command_controller(); EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_VIEW_SOURCE)); EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_PRINT)); EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SAVE_PAGE));
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc index 1e66a34c..3f04913 100644 --- a/chrome/browser/ui/browser_command_controller.cc +++ b/chrome/browser/ui/browser_command_controller.cc
@@ -69,8 +69,11 @@ #endif #if defined(OS_CHROMEOS) +#include "ash/public/cpp/window_pin_type.h" #include "chrome/browser/ui/ash/multi_user/multi_user_context_menu.h" #include "chrome/browser/ui/browser_commands_chromeos.h" +#include "ui/base/clipboard/clipboard.h" +#include "ui/base/clipboard/clipboard_types.h" #endif #if defined(OS_LINUX) && !defined(OS_CHROMEOS) @@ -95,7 +98,7 @@ BrowserCommandController::BrowserCommandController(Browser* browser) : browser_(browser), - command_updater_(this) { + command_updater_(nullptr) { browser_->tab_strip_model()->AddObserver(this); PrefService* local_state = g_browser_process->local_state(); if (local_state) { @@ -242,6 +245,12 @@ UpdateCommandsForFullscreenMode(); } +#if defined(OS_CHROMEOS) +void BrowserCommandController::LockedFullscreenStateChanged() { + UpdateCommandsForLockedFullscreenMode(); +} +#endif + void BrowserCommandController::PrintingStateChanged() { UpdatePrintingState(); } @@ -257,11 +266,30 @@ } //////////////////////////////////////////////////////////////////////////////// -// BrowserCommandController, CommandUpdaterDelegate implementation: +// BrowserCommandController, CommandUpdater implementation: -void BrowserCommandController::ExecuteCommandWithDisposition( - int id, - WindowOpenDisposition disposition) { +bool BrowserCommandController::SupportsCommand(int id) const { + return command_updater_.SupportsCommand(id); +} + +bool BrowserCommandController::IsCommandEnabled(int id) const { + return command_updater_.IsCommandEnabled(id); +} + +bool BrowserCommandController::ExecuteCommand(int id) { + return ExecuteCommandWithDisposition(id, WindowOpenDisposition::CURRENT_TAB); +} + +bool BrowserCommandController::ExecuteCommandWithDisposition( + int id, WindowOpenDisposition disposition) { + // Doesn't go through the command_updater_ to avoid dealing with having a + // naming collision for ExecuteCommandWithDisposition (both + // CommandUpdaterDelegate and CommandUpdater declare this function so we + // choose to not implement CommandUpdaterDelegate inside this class and + // therefore command_updater_ doesn't have the delegate set). + if (!SupportsCommand(id) || !IsCommandEnabled(id)) + return false; + // No commands are enabled if there is not yet any selected tab. // TODO(pkasting): It seems like we should not need this, because either // most/all commands should not have been enabled yet anyway or the ones that @@ -270,7 +298,7 @@ // crashes, e.g. from Windows sending WM_COMMANDs at random times during // window construction. This probably could use closer examination someday. if (browser_->tab_strip_model()->active_index() == TabStripModel::kNoTab) - return; + return true; DCHECK(command_updater_.IsCommandEnabled(id)) << "Invalid/disabled command " << id; @@ -668,6 +696,30 @@ LOG(WARNING) << "Received Unimplemented Command: " << id; break; } + + return true; +} + +void BrowserCommandController::AddCommandObserver(int id, + CommandObserver* observer) { + command_updater_.AddCommandObserver(id, observer); +} + +void BrowserCommandController::RemoveCommandObserver( + int id, CommandObserver* observer) { + command_updater_.RemoveCommandObserver(id, observer); +} + +void BrowserCommandController::RemoveCommandObserver( + CommandObserver* observer) { + command_updater_.RemoveCommandObserver(observer); +} + +bool BrowserCommandController::UpdateCommandEnabled(int id, bool state) { + if (is_locked_fullscreen_) + return false; + + return command_updater_.UpdateCommandEnabled(id, state); } //////////////////////////////////////////////////////////////////////////////// @@ -764,6 +816,9 @@ // (like Back & Forward with initial page load) must have their state // initialized here, otherwise they will be forever disabled. + if (is_locked_fullscreen_) + return; + // Navigation commands command_updater_.UpdateCommandEnabled(IDC_RELOAD, true); command_updater_.UpdateCommandEnabled(IDC_RELOAD_BYPASSING_CACHE, true); @@ -923,6 +978,9 @@ } void BrowserCommandController::UpdateCommandsForIncognitoAvailability() { + if (is_locked_fullscreen_) + return; + UpdateSharedCommandsForIncognitoAvailability(&command_updater_, profile()); if (!IsShowingMainUI()) { @@ -932,6 +990,9 @@ } void BrowserCommandController::UpdateCommandsForTabState() { + if (is_locked_fullscreen_) + return; + WebContents* current_web_contents = browser_->tab_strip_model()->GetActiveWebContents(); if (!current_web_contents) // May be NULL during tab restore. @@ -1011,6 +1072,9 @@ } void BrowserCommandController::UpdateCommandsForDevTools() { + if (is_locked_fullscreen_) + return; + bool dev_tools_enabled = !profile()->GetPrefs()->GetBoolean(prefs::kDevToolsDisabled); command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS, @@ -1030,6 +1094,9 @@ } void BrowserCommandController::UpdateCommandsForBookmarkEditing() { + if (is_locked_fullscreen_) + return; + command_updater_.UpdateCommandEnabled(IDC_BOOKMARK_PAGE, CanBookmarkCurrentPage(browser_)); command_updater_.UpdateCommandEnabled(IDC_BOOKMARK_ALL_TABS, @@ -1040,6 +1107,9 @@ } void BrowserCommandController::UpdateCommandsForBookmarkBar() { + if (is_locked_fullscreen_) + return; + command_updater_.UpdateCommandEnabled( IDC_SHOW_BOOKMARK_BAR, browser_defaults::bookmarks_enabled && !profile()->IsGuestSession() && @@ -1050,11 +1120,17 @@ } void BrowserCommandController::UpdateCommandsForFileSelectionDialogs() { + if (is_locked_fullscreen_) + return; + UpdateSaveAsState(); UpdateOpenFileState(&command_updater_); } void BrowserCommandController::UpdateCommandsForFullscreenMode() { + if (is_locked_fullscreen_) + return; + const bool is_fullscreen = window() && window()->IsFullscreen(); const bool show_main_ui = IsShowingMainUI(); const bool main_not_fullscreen = show_main_ui && !is_fullscreen; @@ -1113,7 +1189,70 @@ UpdateCommandsForIncognitoAvailability(); } +#if defined(OS_CHROMEOS) +namespace { + +#if DCHECK_IS_ON() +// Makes sure that all commands that are not whitelisted are disabled. DCHECKs +// otherwise. Compiled only in debug mode. +void NonWhitelistedCommandsAreDisabled(CommandUpdaterImpl* command_updater) { + constexpr int kWhitelistedIds[] = { + IDC_CUT, IDC_COPY, IDC_PASTE, + IDC_FIND, IDC_FIND_NEXT, IDC_FIND_PREVIOUS, + IDC_ZOOM_PLUS, IDC_ZOOM_NORMAL, IDC_ZOOM_MINUS, + }; + + // Go through all the command ids, skip the whitelisted ones. + for (int id : command_updater->GetAllIds()) { + if (std::find(std::begin(kWhitelistedIds), std::end(kWhitelistedIds), id) + != std::end(kWhitelistedIds)) { + continue; + } + DCHECK(!command_updater->IsCommandEnabled(id)); + } +} +#endif + +} // namespace + +void BrowserCommandController::UpdateCommandsForLockedFullscreenMode() { + // Reset the clipboard when entering or exiting locked fullscreen (security + // concerns). + ui::Clipboard::GetForCurrentThread()->Clear(ui::CLIPBOARD_TYPE_COPY_PASTE); + + bool is_locked_fullscreen = ash::IsWindowTrustedPinned(browser_->window()); + // Sanity check to make sure this function is called only on state change. + DCHECK_NE(is_locked_fullscreen, is_locked_fullscreen_); + if (is_locked_fullscreen == is_locked_fullscreen_) + return; + is_locked_fullscreen_ = is_locked_fullscreen; + + if (is_locked_fullscreen_) { + command_updater_.DisableAllCommands(); + // Update the state of whitelisted commands: + // IDC_CUT/IDC_COPY/IDC_PASTE, + UpdateCommandsForContentRestrictionState(); + // IDC_FIND/IDC_FIND_NEXT/IDC_FIND_PREVIOUS, + UpdateCommandsForFind(); + // IDC_ZOOM_PLUS/IDC_ZOOM_NORMAL/IDC_ZOOM_MINUS. + UpdateCommandsForZoomState(); + // All other commands will be disabled (there is an early return in their + // corresponding UpdateCommandsFor* functions). +#if DCHECK_IS_ON() + NonWhitelistedCommandsAreDisabled(&command_updater_); +#endif + } else { + // Do an init call to re-initialize command state after the + // DisableAllCommands. + InitCommandState(); + } +} +#endif + void BrowserCommandController::UpdatePrintingState() { + if (is_locked_fullscreen_) + return; + bool print_enabled = CanPrint(browser_); command_updater_.UpdateCommandEnabled(IDC_PRINT, print_enabled); #if BUILDFLAG(ENABLE_BASIC_PRINTING) @@ -1123,10 +1262,16 @@ } void BrowserCommandController::UpdateSaveAsState() { + if (is_locked_fullscreen_) + return; + command_updater_.UpdateCommandEnabled(IDC_SAVE_PAGE, CanSavePage(browser_)); } void BrowserCommandController::UpdateShowSyncState(bool show_main_ui) { + if (is_locked_fullscreen_) + return; + command_updater_.UpdateCommandEnabled( IDC_SHOW_SYNC_SETUP, show_main_ui && pref_signin_allowed_.GetValue()); } @@ -1144,11 +1289,17 @@ void BrowserCommandController::UpdateReloadStopState(bool is_loading, bool force) { + if (is_locked_fullscreen_) + return; + window()->UpdateReloadStopState(is_loading, force); command_updater_.UpdateCommandEnabled(IDC_STOP, is_loading); } void BrowserCommandController::UpdateTabRestoreCommandState() { + if (is_locked_fullscreen_) + return; + sessions::TabRestoreService* tab_restore_service = TabRestoreServiceFactory::GetForProfile(profile()); // The command is enabled if the service hasn't loaded yet to trigger loading. @@ -1171,6 +1322,9 @@ } void BrowserCommandController::UpdateCommandsForMediaRouter() { + if (is_locked_fullscreen_) + return; + command_updater_.UpdateCommandEnabled(IDC_ROUTE_MEDIA, CanRouteMedia(browser_)); }
diff --git a/chrome/browser/ui/browser_command_controller.h b/chrome/browser/ui/browser_command_controller.h index e5f23e0..3c194e8 100644 --- a/chrome/browser/ui/browser_command_controller.h +++ b/chrome/browser/ui/browser_command_controller.h
@@ -7,9 +7,11 @@ #include <vector> +#include "base/gtest_prod_util.h" #include "base/macros.h" #include "chrome/browser/command_updater.h" #include "chrome/browser/command_updater_delegate.h" +#include "chrome/browser/command_updater_impl.h" #include "chrome/browser/ui/tabs/tab_strip_model_observer.h" #include "components/prefs/pref_change_registrar.h" #include "components/prefs/pref_member.h" @@ -26,15 +28,16 @@ namespace chrome { -class BrowserCommandController : public CommandUpdaterDelegate, +// This class needs to expose the internal command_updater_ in some way, hence +// it implements CommandUpdater as the public API for it (so it's not directly +// exposed). +class BrowserCommandController : public CommandUpdater, public TabStripModelObserver, public sessions::TabRestoreServiceObserver { public: explicit BrowserCommandController(Browser* browser); ~BrowserCommandController() override; - CommandUpdater* command_updater() { return &command_updater_; } - // Returns true if |command_id| is a reserved command whose keyboard shortcuts // should not be sent to the renderer or |event| was triggered by a key that // we never want to send to the renderer. @@ -47,10 +50,29 @@ void ZoomStateChanged(); void ContentRestrictionsChanged(); void FullscreenStateChanged(); +#if defined(OS_CHROMEOS) + // Called when the browser goes in or out of the special locked fullscreen + // mode. In this mode the user is basically locked into the current browser + // window and tab hence we disable most keyboard shortcuts and we also + // prevent changing the state of enabled shortcuts while in this mode (so the + // other *Changed() functions will be a NO-OP in this state). + void LockedFullscreenStateChanged(); +#endif void PrintingStateChanged(); void LoadingStateChanged(bool is_loading, bool force); void ExtensionStateChanged(); + // Overriden from CommandUpdater: + bool SupportsCommand(int id) const override; + bool IsCommandEnabled(int id) const override; + bool ExecuteCommand(int id) override; + bool ExecuteCommandWithDisposition(int id, WindowOpenDisposition disposition) + override; + void AddCommandObserver(int id, CommandObserver* observer) override; + void RemoveCommandObserver(int id, CommandObserver* observer) override; + void RemoveCommandObserver(CommandObserver* observer) override; + bool UpdateCommandEnabled(int id, bool state) override; + // Shared state updating: these functions are static and public to share with // outside code. @@ -65,10 +87,8 @@ private: class InterstitialObserver; - - // Overridden from CommandUpdaterDelegate: - void ExecuteCommandWithDisposition(int id, WindowOpenDisposition disposition) - override; + FRIEND_TEST_ALL_PREFIXES(BrowserCommandControllerBrowserTest, + LockedFullscreen); // Overridden from TabStripModelObserver: void TabInsertedAt(TabStripModel* tab_strip_model, @@ -127,6 +147,12 @@ // window is in. void UpdateCommandsForFullscreenMode(); +#if defined(OS_CHROMEOS) + // Update commands whose state depends on whether the window is in locked + // fullscreen mode or not. + void UpdateCommandsForLockedFullscreenMode(); +#endif + // Updates the printing command state. void UpdatePrintingState(); @@ -162,8 +188,8 @@ Browser* const browser_; - // The CommandUpdater that manages the browser window commands. - CommandUpdater command_updater_; + // The CommandUpdaterImpl that manages the browser window commands. + CommandUpdaterImpl command_updater_; std::vector<InterstitialObserver*> interstitial_observers_; @@ -171,6 +197,9 @@ PrefChangeRegistrar local_pref_registrar_; BooleanPrefMember pref_signin_allowed_; + // In locked fullscreen mode disallow enabling/disabling commands. + bool is_locked_fullscreen_ = false; + DISALLOW_COPY_AND_ASSIGN(BrowserCommandController); };
diff --git a/chrome/browser/ui/browser_command_controller_browsertest.cc b/chrome/browser/ui/browser_command_controller_browsertest.cc index ac668b1..6ef9df5 100644 --- a/chrome/browser/ui/browser_command_controller_browsertest.cc +++ b/chrome/browser/ui/browser_command_controller_browsertest.cc
@@ -29,9 +29,15 @@ #include "content/public/test/test_utils.h" #if defined(OS_CHROMEOS) +#include "ash/public/cpp/window_pin_type.h" +#include "ash/public/cpp/window_properties.h" +#include "ash/public/interfaces/window_pin_type.mojom.h" #include "chromeos/chromeos_switches.h" +#include "ui/aura/window.h" #endif +namespace chrome { + class BrowserCommandControllerBrowserTest: public InProcessBrowserTest { public: BrowserCommandControllerBrowserTest() {} @@ -105,8 +111,7 @@ // on to a CallbackList::Subscription forever. TemplateURLServiceFactory::GetForProfile(guest)->set_loaded(true); - const CommandUpdater* command_updater = - browser->command_controller()->command_updater(); + const CommandUpdater* command_updater = browser->command_controller(); #if defined(OS_CHROMEOS) // Chrome OS uses system tray menu to handle multi-profiles. EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_SHOW_AVATAR_MENU)); @@ -114,3 +119,62 @@ EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SHOW_AVATAR_MENU)); #endif } + +#if defined(OS_CHROMEOS) +IN_PROC_BROWSER_TEST_F(BrowserCommandControllerBrowserTest, LockedFullscreen) { + CommandUpdaterImpl* command_updater = + &browser()->command_controller()->command_updater_; + // IDC_EXIT is always enabled in regular mode so it's a perfect candidate for + // testing. + EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_EXIT)); + // Set locked fullscreen mode. + browser()->window()->GetNativeWindow()->SetProperty( + ash::kWindowPinTypeKey, ash::mojom::WindowPinType::TRUSTED_PINNED); + // Update the corresponding command_controller state. + browser()->command_controller()->LockedFullscreenStateChanged(); + // Update some more states just to make sure the wrong commands don't get + // enabled. + browser()->command_controller()->TabStateChanged(); + browser()->command_controller()->FullscreenStateChanged(); + browser()->command_controller()->PrintingStateChanged(); + browser()->command_controller()->ExtensionStateChanged(); + // IDC_EXIT is not enabled in locked fullscreen. + EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_EXIT)); + + constexpr int kWhitelistedIds[] = { + IDC_CUT, IDC_COPY, IDC_PASTE, + IDC_FIND, IDC_FIND_NEXT, IDC_FIND_PREVIOUS, + IDC_ZOOM_PLUS, IDC_ZOOM_NORMAL, IDC_ZOOM_MINUS, + }; + + // Go through all the command ids and make sure all non-whitelisted commands + // are disabled. + for (int id : command_updater->GetAllIds()) { + if (std::find(std::begin(kWhitelistedIds), std::end(kWhitelistedIds), id) + != std::end(kWhitelistedIds)) { + continue; + } + EXPECT_FALSE(command_updater->IsCommandEnabled(id)); + } + + // Verify the set of whitelisted commands. All but IDC_ZOOM_NORMAL should be + // enabled. + for (int id : kWhitelistedIds) { + if (id == IDC_ZOOM_NORMAL) { + EXPECT_FALSE(command_updater->IsCommandEnabled(id)); + continue; + } + EXPECT_TRUE(command_updater->IsCommandEnabled(id)); + } + + // Exit locked fullscreen mode. + browser()->window()->GetNativeWindow()->SetProperty( + ash::kWindowPinTypeKey, ash::mojom::WindowPinType::NONE); + // Update the corresponding command_controller state. + browser()->command_controller()->LockedFullscreenStateChanged(); + // IDC_EXIT is enabled again. + EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_EXIT)); +} +#endif + +} // namespace chrome
diff --git a/chrome/browser/ui/browser_command_controller_unittest.cc b/chrome/browser/ui/browser_command_controller_unittest.cc index 1e681a99..fb7a754 100644 --- a/chrome/browser/ui/browser_command_controller_unittest.cc +++ b/chrome/browser/ui/browser_command_controller_unittest.cc
@@ -159,9 +159,10 @@ TestingProfile* testprofile = browser()->profile()->AsTestingProfile(); EXPECT_TRUE(testprofile); testprofile->SetGuestSession(true); - chrome::BrowserCommandController - ::UpdateSharedCommandsForIncognitoAvailability( - browser()->command_controller()->command_updater(), testprofile); + chrome::BrowserCommandController :: + UpdateSharedCommandsForIncognitoAvailability( + browser()->command_controller(), + testprofile); EXPECT_TRUE(chrome::IsCommandEnabled(browser(), IDC_OPTIONS)); EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_IMPORT_SETTINGS)); EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_SHOW_SIGNIN)); @@ -169,9 +170,10 @@ testprofile->SetGuestSession(false); IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(), IncognitoModePrefs::FORCED); - chrome::BrowserCommandController - ::UpdateSharedCommandsForIncognitoAvailability( - browser()->command_controller()->command_updater(), testprofile); + chrome::BrowserCommandController :: + UpdateSharedCommandsForIncognitoAvailability( + browser()->command_controller(), + testprofile); EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_OPTIONS)); EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_IMPORT_SETTINGS)); EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_SHOW_SIGNIN)); @@ -195,7 +197,7 @@ TestingProfileManager* testing_profile_manager = profile_manager(); ProfileManager* profile_manager = testing_profile_manager->profile_manager(); chrome::BrowserCommandController command_controller(browser()); - const CommandUpdater* command_updater = command_controller.command_updater(); + const CommandUpdater* command_updater = &command_controller; bool enabled = true; #if defined(OS_CHROMEOS) @@ -230,7 +232,7 @@ CreateBrowserWithTestWindowForParams(&profile_params)); chrome::BrowserCommandController command_controller(otr_browser.get()); - const CommandUpdater* command_updater = command_controller.command_updater(); + const CommandUpdater* command_updater = &command_controller; // The avatar menu should be disabled. EXPECT_FALSE(command_updater->IsCommandEnabled(IDC_SHOW_AVATAR_MENU)); @@ -473,7 +475,7 @@ CreateBrowserWithTestWindowForParams(&profile_params)); chrome::BrowserCommandController command_controller(browser2.get()); - const CommandUpdater* command_updater = command_controller.command_updater(); + const CommandUpdater* command_updater = &command_controller; // Check that the SYNC_SETUP command is updated on preference change. EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SHOW_SYNC_SETUP)); @@ -483,7 +485,7 @@ TEST_F(BrowserCommandControllerTest, OnSigninAllowedPrefChange) { chrome::BrowserCommandController command_controller(browser()); - const CommandUpdater* command_updater = command_controller.command_updater(); + const CommandUpdater* command_updater = &command_controller; // Check that the SYNC_SETUP command is updated on preference change. EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_SHOW_SYNC_SETUP));
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc index 62aed4a..928bcaf 100644 --- a/chrome/browser/ui/browser_commands.cc +++ b/chrome/browser/ui/browser_commands.cc
@@ -306,44 +306,38 @@ } // namespace bool IsCommandEnabled(Browser* browser, int command) { - return browser->command_controller()->command_updater()->IsCommandEnabled( - command); + return browser->command_controller()->IsCommandEnabled(command); } bool SupportsCommand(Browser* browser, int command) { - return browser->command_controller()->command_updater()->SupportsCommand( - command); + return browser->command_controller()->SupportsCommand(command); } bool ExecuteCommand(Browser* browser, int command) { - return browser->command_controller()->command_updater()->ExecuteCommand( - command); + return browser->command_controller()->ExecuteCommand(command); } bool ExecuteCommandWithDisposition(Browser* browser, int command, WindowOpenDisposition disposition) { - return browser->command_controller()->command_updater()-> - ExecuteCommandWithDisposition(command, disposition); + return browser->command_controller()->ExecuteCommandWithDisposition( + command, disposition); } void UpdateCommandEnabled(Browser* browser, int command, bool enabled) { - browser->command_controller()->command_updater()->UpdateCommandEnabled( - command, enabled); + browser->command_controller()->UpdateCommandEnabled(command, enabled); } void AddCommandObserver(Browser* browser, int command, CommandObserver* observer) { - browser->command_controller()->command_updater()->AddCommandObserver( - command, observer); + browser->command_controller()->AddCommandObserver(command, observer); } void RemoveCommandObserver(Browser* browser, int command, CommandObserver* observer) { - browser->command_controller()->command_updater()->RemoveCommandObserver( - command, observer); + browser->command_controller()->RemoveCommandObserver(command, observer); } int GetContentRestrictions(const Browser* browser) {
diff --git a/chrome/browser/ui/browser_unittest.cc b/chrome/browser/ui/browser_unittest.cc index 9e99d68..ad22f6b 100644 --- a/chrome/browser/ui/browser_unittest.cc +++ b/chrome/browser/ui/browser_unittest.cc
@@ -104,8 +104,7 @@ tab_strip_model->AppendWebContents(contents, true); WebContentsTester::For(contents)->NavigateAndCommit(GURL("about:blank")); - CommandUpdater* command_updater = - browser()->command_controller()->command_updater(); + CommandUpdater* command_updater = browser()->command_controller(); EXPECT_FALSE(contents->IsCrashed()); EXPECT_TRUE(command_updater->IsCommandEnabled(IDC_PRINT)); @@ -130,8 +129,7 @@ EXPECT_TRUE(zoom_controller->SetZoomLevel(zoom_controller-> GetDefaultZoomLevel())); - CommandUpdater* command_updater = - browser()->command_controller()->command_updater(); + CommandUpdater* command_updater = browser()->command_controller(); EXPECT_TRUE(zoom_controller->IsAtDefaultZoom()); EXPECT_FALSE(contents->IsCrashed());
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm index ca792ec..3ce0f4d 100644 --- a/chrome/browser/ui/cocoa/browser_window_controller.mm +++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -366,7 +366,7 @@ // registering for the appropriate command state changes from the back-end. // Adds the toolbar to the content area. toolbarController_.reset([[ToolbarController alloc] - initWithCommands:browser->command_controller()->command_updater() + initWithCommands:browser->command_controller() profile:browser->profile() browser:browser]); [[toolbarController_ toolbarView] setResizeDelegate:self];
diff --git a/chrome/browser/ui/cocoa/browser_window_touch_bar.mm b/chrome/browser/ui/cocoa/browser_window_touch_bar.mm index 381f9435..766468e 100644 --- a/chrome/browser/ui/cocoa/browser_window_touch_bar.mm +++ b/chrome/browser/ui/cocoa/browser_window_touch_bar.mm
@@ -206,7 +206,7 @@ notificationBridge_.reset( new BrowserTouchBarNotificationBridge(self, bwc_)); - commandUpdater_ = browser->command_controller()->command_updater(); + commandUpdater_ = browser->command_controller(); commandUpdater_->AddCommandObserver(IDC_BACK, notificationBridge_.get()); commandUpdater_->AddCommandObserver(IDC_FORWARD, notificationBridge_.get());
diff --git a/chrome/browser/ui/cocoa/browser_window_touch_bar_unittest.mm b/chrome/browser/ui/cocoa/browser_window_touch_bar_unittest.mm index c463199..ef7cbf0 100644 --- a/chrome/browser/ui/cocoa/browser_window_touch_bar_unittest.mm +++ b/chrome/browser/ui/cocoa/browser_window_touch_bar_unittest.mm
@@ -59,7 +59,7 @@ isKindOfClass:[BrowserWindowController class]]; [[bwc_ stub] invalidateTouchBar]; - command_updater_ = browser()->command_controller()->command_updater(); + command_updater_ = browser()->command_controller(); touch_bar_.reset([[BrowserWindowTouchBar alloc] initWithBrowser:browser() browserWindowController:bwc_]);
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 69f9b86..cc6cf3f 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
@@ -192,8 +192,11 @@ autofill::SaveCardBubbleControllerImpl* controller = autofill::SaveCardBubbleControllerImpl::FromWebContents(web_contents); bool enabled = controller && controller->IsIconVisible(); - command_updater()->UpdateCommandEnabled(IDC_SAVE_CREDIT_CARD_FOR_PAGE, - enabled); + if (!command_updater()->UpdateCommandEnabled( + IDC_SAVE_CREDIT_CARD_FOR_PAGE, enabled)) { + enabled = enabled && command_updater()->IsCommandEnabled( + IDC_SAVE_CREDIT_CARD_FOR_PAGE); + } save_credit_card_decoration_->SetIcon(IsLocationBarDark()); save_credit_card_decoration_->SetVisible(enabled); OnDecorationsChanged(); @@ -626,7 +629,10 @@ translate::LanguageState& language_state = ChromeTranslateClient::FromWebContents(web_contents)->GetLanguageState(); bool enabled = language_state.translate_enabled(); - command_updater()->UpdateCommandEnabled(IDC_TRANSLATE_PAGE, enabled); + if (!command_updater()->UpdateCommandEnabled(IDC_TRANSLATE_PAGE, enabled)) { + enabled = enabled && command_updater()->IsCommandEnabled( + IDC_TRANSLATE_PAGE); + } translate_decoration_->SetVisible(enabled); translate_decoration_->SetLit(language_state.IsPageTranslated(), IsLocationBarDark());
diff --git a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac_unittest.mm b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac_unittest.mm index 799a6837..1fbe28e 100644 --- a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac_unittest.mm +++ b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac_unittest.mm
@@ -154,16 +154,16 @@ field_.reset([[AutocompleteTextField alloc] initWithFrame:frame]); location_bar_.reset(new TestingLocationBarViewMac( - field_.get(), browser()->command_controller()->command_updater(), - browser()->profile(), browser())); + field_.get(), browser()->command_controller(), browser()->profile(), + browser())); location_bar_->page_info_decoration_.reset( new TestingPageInfoBubbleDecoration(location_bar_.get())); decoration()->disable_animations_during_testing_ = true; - omnibox_view_ = new MockOmniboxView( - nullptr, browser()->profile(), - browser()->command_controller()->command_updater(), field_.get()); + omnibox_view_ = + new MockOmniboxView(nullptr, browser()->profile(), + browser()->command_controller(), field_.get()); location_bar_->omnibox_view_.reset(omnibox_view_); }
diff --git a/chrome/browser/ui/cocoa/location_bar/manage_passwords_decoration_unittest.mm b/chrome/browser/ui/cocoa/location_bar/manage_passwords_decoration_unittest.mm index ba66380..2fadb5c 100644 --- a/chrome/browser/ui/cocoa/location_bar/manage_passwords_decoration_unittest.mm +++ b/chrome/browser/ui/cocoa/location_bar/manage_passwords_decoration_unittest.mm
@@ -7,8 +7,8 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/app/vector_icons/vector_icons.h" -#include "chrome/browser/command_updater.h" #include "chrome/browser/command_updater_delegate.h" +#include "chrome/browser/command_updater_impl.h" #include "chrome/browser/ui/cocoa/location_bar/manage_passwords_decoration.h" #include "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h" #include "chrome/browser/ui/cocoa/test/cocoa_test_helper.h" @@ -68,7 +68,7 @@ private: TestCommandUpdaterDelegate commandDelegate_; - CommandUpdater commandUpdater_; + CommandUpdaterImpl commandUpdater_; ManagePasswordsDecoration decoration_; };
diff --git a/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm b/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm index 139e270..760bc9b 100644 --- a/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/toolbar/toolbar_controller_unittest.mm
@@ -12,6 +12,7 @@ #include "chrome/browser/command_updater.h" #include "chrome/browser/extensions/extension_action_test_util.h" #include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/load_error_reporter.h" #include "chrome/browser/extensions/test_extension_system.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_command_controller.h" @@ -112,7 +113,7 @@ extensions::ExtensionSystem::Get(profile()) ->extension_service() ->AddExtension(extension.get()); - ExtensionErrorReporter::Init(true); + extensions::LoadErrorReporter::Init(true); ToolbarActionsModel* model = extensions::extension_action_test_util::CreateToolbarModelForProfile( profile()); @@ -120,14 +121,13 @@ resizeDelegate_.reset([[ViewResizerPong alloc] init]); - CommandUpdater* updater = - browser()->command_controller()->command_updater(); + CommandUpdater* updater = browser()->command_controller(); // The default state for the commands is true, set a couple to false to // ensure they get picked up correct on initialization updater->UpdateCommandEnabled(IDC_BACK, false); updater->UpdateCommandEnabled(IDC_FORWARD, false); bar_.reset([[TestToolbarController alloc] - initWithCommands:browser()->command_controller()->command_updater() + initWithCommands:browser()->command_controller() profile:profile() browser:browser()]); [[bar_ toolbarView] setResizeDelegate:resizeDelegate_.get()]; @@ -179,7 +179,7 @@ // Test the initial state that everything is sync'd up TEST_F(ToolbarControllerTest, InitialState) { - CommandUpdater* updater = browser()->command_controller()->command_updater(); + CommandUpdater* updater = browser()->command_controller(); CompareState(updater, [bar_ toolbarViews]); } @@ -312,7 +312,7 @@ EXPECT_FALSE(chrome::IsCommandEnabled(browser(), IDC_FORWARD)); chrome::UpdateCommandEnabled(browser(), IDC_BACK, true); chrome::UpdateCommandEnabled(browser(), IDC_FORWARD, true); - CommandUpdater* updater = browser()->command_controller()->command_updater(); + CommandUpdater* updater = browser()->command_controller(); CompareState(updater, [bar_ toolbarViews]); // Change an unwatched command and ensure the last state does not change.
diff --git a/chrome/browser/ui/media_router/presentation_receiver_window.h b/chrome/browser/ui/media_router/presentation_receiver_window.h new file mode 100644 index 0000000..b374947 --- /dev/null +++ b/chrome/browser/ui/media_router/presentation_receiver_window.h
@@ -0,0 +1,51 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_MEDIA_ROUTER_PRESENTATION_RECEIVER_WINDOW_H_ +#define CHROME_BROWSER_UI_MEDIA_ROUTER_PRESENTATION_RECEIVER_WINDOW_H_ + +namespace gfx { +class Rect; +} + +class PresentationReceiverWindowDelegate; + +// This interface represents a window used to render a receiver page for the +// Presentation API. It should display a WebContents provided by its controller +// and a location bar. The window is not owned by the caller of Create (for +// Views, it is owned by the native widget and Views hierarchy). It will call +// WindowClosing on |delegate| before being destroyed. +class PresentationReceiverWindow { + public: + static PresentationReceiverWindow* Create( + PresentationReceiverWindowDelegate* delegate, + const gfx::Rect& bounds); + + // Closes the window. + virtual void Close() = 0; + + // Returns true if the window is active (i.e. has focus). + virtual bool IsWindowActive() const = 0; + + // Returns true if the window is currently fullscreened. + virtual bool IsWindowFullscreen() const = 0; + + // Returns the current bounds of the window. + virtual gfx::Rect GetWindowBounds() const = 0; + + // Shows the window as inactive and transitions it to fullscreen. + virtual void ShowInactiveFullscreen() = 0; + + // Updates the window title if it has changed. + virtual void UpdateWindowTitle() = 0; + + // Updates the location bar if the location of the displayed WebContents has + // changed. + virtual void UpdateLocationBar() = 0; + + protected: + ~PresentationReceiverWindow() = default; +}; + +#endif // CHROME_BROWSER_UI_MEDIA_ROUTER_PRESENTATION_RECEIVER_WINDOW_H_
diff --git a/chrome/browser/ui/media_router/presentation_receiver_window_controller.cc b/chrome/browser/ui/media_router/presentation_receiver_window_controller.cc new file mode 100644 index 0000000..c3e48c9 --- /dev/null +++ b/chrome/browser/ui/media_router/presentation_receiver_window_controller.cc
@@ -0,0 +1,201 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/media_router/presentation_receiver_window_controller.h" + +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "chrome/browser/media/router/receiver_presentation_service_delegate_impl.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/media_router/presentation_receiver_window.h" +#include "content/public/browser/navigation_controller.h" +#include "content/public/browser/web_contents.h" +#include "third_party/WebKit/public/web/WebPresentationReceiverFlags.h" +#include "ui/views/widget/widget.h" + +using content::WebContents; + +namespace { + +WebContents::CreateParams CreateWebContentsParams(Profile* profile) { + WebContents::CreateParams params(profile); + params.starting_sandbox_flags = blink::kPresentationReceiverSandboxFlags; + return params; +} + +} // namespace + +// static +std::unique_ptr<PresentationReceiverWindowController> +PresentationReceiverWindowController::CreateFromOriginalProfile( + Profile* profile, + const gfx::Rect& bounds, + base::OnceClosure termination_callback) { + DCHECK(profile); + DCHECK(!profile->IsOffTheRecord()); + DCHECK(termination_callback); + return base::WrapUnique(new PresentationReceiverWindowController( + profile, bounds, std::move(termination_callback))); +} + +PresentationReceiverWindowController::~PresentationReceiverWindowController() { + DCHECK(!web_contents_); + DCHECK(!window_); +} + +void PresentationReceiverWindowController::Start( + const std::string& presentation_id, + const GURL& start_url) { + DCHECK(window_); + DCHECK(web_contents_); + + media_router::ReceiverPresentationServiceDelegateImpl::CreateForWebContents( + web_contents_.get(), presentation_id); + + content::NavigationController::LoadURLParams load_params(start_url); + load_params.should_replace_current_entry = true; + load_params.should_clear_history_list = true; + web_contents_->GetController().LoadURLWithParams(load_params); + + window_->ShowInactiveFullscreen(); +} + +void PresentationReceiverWindowController::Terminate() { + if (web_contents_) { + web_contents_->ClosePage(); + } else if (window_) { + window_->Close(); + } else if (termination_callback_) { + std::move(termination_callback_).Run(); + } +} + +void PresentationReceiverWindowController::CloseWindowForTest() { + window_->Close(); +} + +bool PresentationReceiverWindowController::IsWindowActiveForTest() const { + return window_->IsWindowActive(); +} + +bool PresentationReceiverWindowController::IsWindowFullscreenForTest() const { + return window_->IsWindowFullscreen(); +} + +gfx::Rect PresentationReceiverWindowController::GetWindowBoundsForTest() const { + return window_->GetWindowBounds(); +} + +WebContents* PresentationReceiverWindowController::web_contents() const { + return web_contents_.get(); +} + +PresentationReceiverWindowController::PresentationReceiverWindowController( + Profile* profile, + const gfx::Rect& bounds, + base::OnceClosure termination_callback) + : otr_profile_registration_( + IndependentOTRProfileManager::GetInstance() + ->CreateFromOriginalProfile( + profile, + base::BindOnce(&PresentationReceiverWindowController:: + OriginalProfileDestroyed, + base::Unretained(this)))), + web_contents_(WebContents::Create( + CreateWebContentsParams(otr_profile_registration_->profile()))), + window_(PresentationReceiverWindow::Create(this, bounds)), + termination_callback_(std::move(termination_callback)) { + DCHECK(otr_profile_registration_->profile()); + DCHECK(otr_profile_registration_->profile()->IsOffTheRecord()); + content::WebContentsObserver::Observe(web_contents_.get()); + web_contents_->SetDelegate(this); +} + +void PresentationReceiverWindowController::WindowClosed() { + window_ = nullptr; + Terminate(); +} + +void PresentationReceiverWindowController::OriginalProfileDestroyed( + Profile* profile) { + DCHECK(profile == otr_profile_registration_->profile()); + web_contents_.reset(); + otr_profile_registration_.reset(); + Terminate(); +} + +void PresentationReceiverWindowController::DidStartNavigation( + content::NavigationHandle* handle) { + if (!navigation_policy_.AllowNavigation(handle)) + Terminate(); +} + +void PresentationReceiverWindowController::TitleWasSet( + content::NavigationEntry* entry) { + window_->UpdateWindowTitle(); +} + +void PresentationReceiverWindowController::NavigationStateChanged( + WebContents* source, + content::InvalidateTypes changed_flags) { + window_->UpdateLocationBar(); +} + +void PresentationReceiverWindowController::CloseContents( + content::WebContents* source) { + web_contents_.reset(); + Terminate(); +} + +bool PresentationReceiverWindowController::ShouldSuppressDialogs( + content::WebContents* source) { + DCHECK_EQ(web_contents_.get(), source); + // Suppress all because there is no possible direct user interaction with + // dialogs. + // TODO(https://crbug.com/734191): This does not suppress window.print(). + return true; +} + +bool PresentationReceiverWindowController::ShouldFocusLocationBarByDefault( + content::WebContents* source) { + DCHECK_EQ(web_contents_.get(), source); + // Indicate the location bar should be focused instead of the page, even + // though there is no location bar in fullscreen (the presentation's default + // state). This will prevent the page from automatically receiving input + // focus, which is usually not intended. + return true; +} + +bool PresentationReceiverWindowController::ShouldFocusPageAfterCrash() { + // Never focus the page after a crash. + return false; +} + +void PresentationReceiverWindowController::CanDownload( + const GURL& url, + const std::string& request_method, + const base::Callback<void(bool)>& callback) { + // Local presentation pages are not allowed to download files. + callback.Run(false); +} + +bool PresentationReceiverWindowController::ShouldCreateWebContents( + content::WebContents* web_contents, + content::RenderFrameHost* opener, + content::SiteInstance* source_site_instance, + int32_t route_id, + int32_t main_frame_route_id, + int32_t main_frame_widget_route_id, + content::mojom::WindowContainerType window_container_type, + const GURL& opener_url, + const std::string& frame_name, + const GURL& target_url, + const std::string& partition_id, + content::SessionStorageNamespace* session_storage_namespace) { + DCHECK_EQ(web_contents_.get(), web_contents); + // Disallow creating separate WebContentses. The WebContents implementation + // uses this to spawn new windows/tabs, which is also not allowed for + // local presentations. + return false; +}
diff --git a/chrome/browser/ui/media_router/presentation_receiver_window_controller.h b/chrome/browser/ui/media_router/presentation_receiver_window_controller.h new file mode 100644 index 0000000..a0562fd --- /dev/null +++ b/chrome/browser/ui/media_router/presentation_receiver_window_controller.h
@@ -0,0 +1,121 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_MEDIA_ROUTER_PRESENTATION_RECEIVER_WINDOW_CONTROLLER_H_ +#define CHROME_BROWSER_UI_MEDIA_ROUTER_PRESENTATION_RECEIVER_WINDOW_CONTROLLER_H_ + +#include <memory> +#include <string> + +#include "base/callback.h" +#include "base/macros.h" +#include "chrome/browser/media/router/independent_otr_profile_manager.h" +#include "chrome/browser/media/router/presentation_navigation_policy.h" +#include "chrome/browser/ui/media_router/presentation_receiver_window_delegate.h" +#include "content/public/browser/web_contents_delegate.h" +#include "content/public/browser/web_contents_observer.h" + +class GURL; +class PresentationReceiverWindow; +class Profile; + +namespace content { +class WebContents; +} + +namespace gfx { +class Rect; +} + +// This class controls a window which is used to render a receiver page for the +// Presentation API. It handles creating the window to show the desired URL and +// showing it in fullscreen on the desired display. This class should not be +// destroyed until |termination_callback| has been called, which may be called +// before Terminate() is ever called. +class PresentationReceiverWindowController final + : public PresentationReceiverWindowDelegate, + public content::WebContentsObserver, + public content::WebContentsDelegate { + public: + static std::unique_ptr<PresentationReceiverWindowController> + CreateFromOriginalProfile(Profile* profile, + const gfx::Rect& bounds, + base::OnceClosure termination_callback); + + ~PresentationReceiverWindowController() final; + + // Starts the presentation with the receiver page |start_url| and the + // presentation ID |presentation_id| for the purpose of messaging. + void Start(const std::string& presentation_id, const GURL& start_url); + + // Closes the window and stops the presentation. + void Terminate(); + + // PresentationReceiverWindowDelegate overrides. + content::WebContents* web_contents() const final; + + private: + friend class PresentationReceiverWindowControllerBrowserTest; + + PresentationReceiverWindowController(Profile* profile, + const gfx::Rect& bounds, + base::OnceClosure termination_callback); + + void OriginalProfileDestroyed(Profile* profile); + + // These methods are intended to be used by tests. + void CloseWindowForTest(); + bool IsWindowActiveForTest() const; + bool IsWindowFullscreenForTest() const; + gfx::Rect GetWindowBoundsForTest() const; + + // PresentationReceiverWindowDelegate overrides. + void WindowClosed() final; + + // content::WebContentsObserver overrides. + void DidStartNavigation(content::NavigationHandle* handle) final; + void TitleWasSet(content::NavigationEntry* entry) final; + + // content::WebContentsDelegate overrides. + void NavigationStateChanged(content::WebContents* source, + content::InvalidateTypes changed_flags) final; + void CloseContents(content::WebContents* source) final; + bool ShouldSuppressDialogs(content::WebContents* source) final; + bool ShouldFocusLocationBarByDefault(content::WebContents* source) final; + bool ShouldFocusPageAfterCrash() final; + void CanDownload(const GURL& url, + const std::string& request_method, + const base::Callback<void(bool)>& callback) final; + bool ShouldCreateWebContents( + content::WebContents* web_contents, + content::RenderFrameHost* opener, + content::SiteInstance* source_site_instance, + int32_t route_id, + int32_t main_frame_route_id, + int32_t main_frame_widget_route_id, + content::mojom::WindowContainerType window_container_type, + const GURL& opener_url, + const std::string& frame_name, + const GURL& target_url, + const std::string& partition_id, + content::SessionStorageNamespace* session_storage_namespace) final; + + // The profile used for the presentation. + std::unique_ptr<IndependentOTRProfileManager::OTRProfileRegistration> + otr_profile_registration_; + + // WebContents for rendering the receiver page. + std::unique_ptr<content::WebContents> web_contents_; + + // The actual UI window for displaying the receiver page. + PresentationReceiverWindow* window_; + + base::OnceClosure termination_callback_; + + media_router::PresentationNavigationPolicy navigation_policy_; + + DISALLOW_COPY_AND_ASSIGN(PresentationReceiverWindowController); +}; + +#endif // CHROME_BROWSER_UI_MEDIA_ROUTER_PRESENTATION_RECEIVER_WINDOW_CONTROLLER_H_
diff --git a/chrome/browser/ui/media_router/presentation_receiver_window_controller_browsertest.cc b/chrome/browser/ui/media_router/presentation_receiver_window_controller_browsertest.cc new file mode 100644 index 0000000..0690fd87 --- /dev/null +++ b/chrome/browser/ui/media_router/presentation_receiver_window_controller_browsertest.cc
@@ -0,0 +1,343 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/media_router/presentation_receiver_window_controller.h" + +#include <string> + +#include "base/files/file_path.h" +#include "base/macros.h" +#include "base/path_service.h" +#include "base/run_loop.h" +#include "base/task_scheduler/post_task.h" +#include "base/threading/thread_restrictions.h" +#include "base/timer/elapsed_timer.h" +#include "chrome/browser/media/router/local_presentation_manager.h" +#include "chrome/browser/media/router/local_presentation_manager_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "content/public/browser/navigation_controller.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/web_contents_observer.h" +#include "content/public/common/presentation_connection_message.h" +#include "content/public/common/presentation_info.h" +#include "content/public/test/browser_test_utils.h" +#include "extensions/browser/script_executor.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "net/base/filename_util.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "third_party/WebKit/public/platform/modules/presentation/presentation.mojom.h" +#include "ui/display/display.h" +#include "ui/display/screen.h" +#include "ui/views/widget/widget.h" +#include "url/gurl.h" + +namespace { + +using RenderFrameHostId = std::pair<int, int>; + +constexpr char kPresentationId[] = "test_id"; +const base::FilePath::StringPieceType kResourcePath = + FILE_PATH_LITERAL("media/router/"); + +base::FilePath GetResourceFile(base::FilePath::StringPieceType relative_path) { + base::FilePath base_dir; + if (!PathService::Get(chrome::DIR_TEST_DATA, &base_dir)) + return base::FilePath(); + base::FilePath full_path = + base_dir.Append(kResourcePath).Append(relative_path); + { + base::ScopedAllowBlockingForTesting scoped_allow_blocking; + if (!PathExists(full_path)) + return base::FilePath(); + } + return full_path; +} + +// This class waits for a WebContents it is assigned via Observe to be destroyed +// and then quits a RunLoop it is given. This is used in tests to wait for the +// receiver page to be torn down in the presentation window. +class CloseObserver final : public content::WebContentsObserver { + public: + explicit CloseObserver(base::RunLoop* run_loop) : run_loop_(run_loop) {} + + // content::WebContentsObserver overrides. + void WebContentsDestroyed() override { run_loop_->Quit(); } + + using content::WebContentsObserver::Observe; + + private: + base::RunLoop* const run_loop_; + + DISALLOW_COPY_AND_ASSIGN(CloseObserver); +}; + +// This class imitates a presentation controller page from a messaging +// standpoint. It is registered as a controller connection for the appropriate +// presentation ID with the LocalPresentationManager to facilitate a +// presentation API communication test with the receiver window. +class FakeControllerConnection final + : public blink::mojom::PresentationConnection { + public: + using OnMessageCallback = base::OnceCallback<void(bool)>; + + FakeControllerConnection() : binding_(this) {} + + void SendTextMessage(const std::string& message) { + ASSERT_TRUE(receiver_connection_.is_bound()); + receiver_connection_->OnMessage( + content::PresentationConnectionMessage(message), + base::BindOnce([](bool success) { ASSERT_TRUE(success); })); + } + + // blink::mojom::PresentationConnection implementation + void OnMessage(content::PresentationConnectionMessage message, + OnMessageCallback callback) { + OnMessageMock(message); + std::move(callback).Run(true); + } + MOCK_METHOD1(OnMessageMock, + void(content::PresentationConnectionMessage message)); + void DidChangeState(content::PresentationConnectionState state) override {} + void RequestClose() override {} + + blink::mojom::PresentationConnectionRequest MakeConnectionRequest() { + return mojo::MakeRequest(&receiver_connection_); + } + blink::mojom::PresentationConnectionPtr Bind() { + blink::mojom::PresentationConnectionPtr connection; + binding_.Bind(mojo::MakeRequest(&connection)); + return connection; + } + + private: + mojo::Binding<blink::mojom::PresentationConnection> binding_; + blink::mojom::PresentationConnectionPtr receiver_connection_; + + DISALLOW_COPY_AND_ASSIGN(FakeControllerConnection); +}; + +// This class is used to wait for Terminate to finish before destroying a +// PresentationReceiverWindowController. It destroys it as soon as its +// termination callback is called (OnTerminate). This is in contrast to just +// using a RunLoop with a QuitClosure callback in each test. The latter allows +// extra events in the RunLoop to be handled before actually destroying the +// PresentationReceiverWindowController, which doesn't test whether it's +// actually safe to destroy it in the termination callback itself. +class ReceiverWindowDestroyer { + public: + ReceiverWindowDestroyer() = default; + ~ReceiverWindowDestroyer() = default; + + void AwaitTerminate( + std::unique_ptr<PresentationReceiverWindowController> receiver_window) { + receiver_window_ = std::move(receiver_window); + receiver_window_->Terminate(); + run_loop_.Run(); + } + + void OnTerminate() { + receiver_window_.reset(); + run_loop_.Quit(); + } + + private: + base::RunLoop run_loop_; + std::unique_ptr<PresentationReceiverWindowController> receiver_window_; +}; + +} // namespace + +class PresentationReceiverWindowControllerBrowserTest + : public InProcessBrowserTest { + protected: + void CloseWindow(PresentationReceiverWindowController* receiver_window) { + receiver_window->CloseWindowForTest(); + } + + bool IsWindowFullscreen( + const PresentationReceiverWindowController& receiver_window) { + return receiver_window.IsWindowFullscreenForTest(); + } + + bool IsWindowActive( + const PresentationReceiverWindowController& receiver_window) { + return receiver_window.IsWindowActiveForTest(); + } + + gfx::Rect GetWindowBounds( + const PresentationReceiverWindowController& receiver_window) { + return receiver_window.GetWindowBoundsForTest(); + } +}; + +IN_PROC_BROWSER_TEST_F(PresentationReceiverWindowControllerBrowserTest, + CreatesWindow) { + ReceiverWindowDestroyer destroyer; + auto receiver_window = + PresentationReceiverWindowController::CreateFromOriginalProfile( + browser()->profile(), gfx::Rect(100, 100), + base::BindOnce(&ReceiverWindowDestroyer::OnTerminate, + base::Unretained(&destroyer))); + receiver_window->Start(kPresentationId, GURL("about:blank")); + base::RunLoop().RunUntilIdle(); + + EXPECT_TRUE(IsWindowFullscreen(*receiver_window)); + + destroyer.AwaitTerminate(std::move(receiver_window)); +} + +IN_PROC_BROWSER_TEST_F(PresentationReceiverWindowControllerBrowserTest, + MANUAL_CreatesWindowOnGivenDisplay) { + // Pick specific display. + auto* screen = display::Screen::GetScreen(); + const auto& displays = screen->GetAllDisplays(); + for (const auto& display : displays) { + DVLOG(0) << display.ToString(); + } + + // Choose a non-default display to which to move the receiver window. + ASSERT_LE(2ul, displays.size()); + const auto default_display = + screen->GetDisplayNearestWindow(browser()->window()->GetNativeWindow()); + display::Display target_display; + ASSERT_FALSE(target_display.is_valid()); + for (const auto& display : displays) { + if (display.id() != default_display.id()) { + target_display = display; + break; + } + } + ASSERT_TRUE(target_display.is_valid()); + + ReceiverWindowDestroyer destroyer; + auto receiver_window = + PresentationReceiverWindowController::CreateFromOriginalProfile( + browser()->profile(), target_display.bounds(), + base::BindOnce(&ReceiverWindowDestroyer::OnTerminate, + base::Unretained(&destroyer))); + receiver_window->Start(kPresentationId, GURL("about:blank")); + ASSERT_TRUE(content::WaitForLoadStop(receiver_window->web_contents())); + + // Check the window is on the correct display. + const auto display = + screen->GetDisplayMatching(GetWindowBounds(*receiver_window)); + EXPECT_EQ(display.id(), target_display.id()); + + // The inactive test won't work on single-display systems because fullscreen + // forces it to have focus, so it must be part of the manual test with 2+ + // displays. + EXPECT_FALSE(IsWindowActive(*receiver_window)); + + destroyer.AwaitTerminate(std::move(receiver_window)); +} + +IN_PROC_BROWSER_TEST_F(PresentationReceiverWindowControllerBrowserTest, + NavigationClosesWindow) { + // Start receiver window. + auto file_path = + GetResourceFile(FILE_PATH_LITERAL("presentation_receiver.html")); + ASSERT_FALSE(file_path.empty()); + const GURL presentation_url = net::FilePathToFileURL(file_path); + ReceiverWindowDestroyer destroyer; + auto receiver_window = + PresentationReceiverWindowController::CreateFromOriginalProfile( + browser()->profile(), gfx::Rect(100, 100), + base::BindOnce(&ReceiverWindowDestroyer::OnTerminate, + base::Unretained(&destroyer))); + receiver_window->Start(kPresentationId, presentation_url); + ASSERT_TRUE(content::WaitForLoadStop(receiver_window->web_contents())); + + base::RunLoop run_loop; + CloseObserver close_observer(&run_loop); + close_observer.Observe(receiver_window->web_contents()); + + ASSERT_TRUE(content::ExecuteScript(receiver_window->web_contents(), + "window.location = 'about:blank'")); + run_loop.Run(); + + destroyer.AwaitTerminate(std::move(receiver_window)); +} + +IN_PROC_BROWSER_TEST_F(PresentationReceiverWindowControllerBrowserTest, + PresentationApiCommunication) { + // Start receiver window. + auto file_path = + GetResourceFile(FILE_PATH_LITERAL("presentation_receiver.html")); + ASSERT_FALSE(file_path.empty()); + const GURL presentation_url = net::FilePathToFileURL(file_path); + ReceiverWindowDestroyer destroyer; + auto receiver_window = + PresentationReceiverWindowController::CreateFromOriginalProfile( + browser()->profile(), gfx::Rect(100, 100), + base::BindOnce(&ReceiverWindowDestroyer::OnTerminate, + base::Unretained(&destroyer))); + receiver_window->Start(kPresentationId, presentation_url); + + // Register controller with LocalPresentationManager using test-local + // implementation of blink::mojom::PresentationConnection. + FakeControllerConnection controller_connection; + auto controller_ptr = controller_connection.Bind(); + media_router::LocalPresentationManagerFactory::GetOrCreateForBrowserContext( + browser()->profile()) + ->RegisterLocalPresentationController( + content::PresentationInfo(presentation_url, kPresentationId), + RenderFrameHostId(0, 0), std::move(controller_ptr), + controller_connection.MakeConnectionRequest(), + media_router::MediaRoute("route", + media_router::MediaSource(presentation_url), + "sink", "desc", true, true)); + + base::RunLoop connection_loop; + EXPECT_CALL(controller_connection, OnMessageMock(::testing::_)) + .WillOnce(::testing::Invoke( + [&connection_loop](content::PresentationConnectionMessage msg) { + ASSERT_TRUE(msg.message); + EXPECT_EQ("ready", *msg.message); + connection_loop.Quit(); + })); + connection_loop.Run(); + + // Test ping-pong message. + const std::string message("turtles"); + base::RunLoop run_loop; + EXPECT_CALL(controller_connection, OnMessageMock(::testing::_)) + .WillOnce(::testing::Invoke( + [&run_loop, + &message](content::PresentationConnectionMessage response) { + ASSERT_TRUE(response.message); + EXPECT_EQ("Pong: " + message, *response.message); + run_loop.Quit(); + })); + controller_connection.SendTextMessage(message); + run_loop.Run(); + + destroyer.AwaitTerminate(std::move(receiver_window)); +} + +IN_PROC_BROWSER_TEST_F(PresentationReceiverWindowControllerBrowserTest, + WindowClosingTerminatesPresentation) { + // Start receiver window. + ReceiverWindowDestroyer destroyer; + auto receiver_window = + PresentationReceiverWindowController::CreateFromOriginalProfile( + browser()->profile(), gfx::Rect(100, 100), + base::BindOnce(&ReceiverWindowDestroyer::OnTerminate, + base::Unretained(&destroyer))); + receiver_window->Start(kPresentationId, GURL("about:blank")); + ASSERT_TRUE(content::WaitForLoadStop(receiver_window->web_contents())); + + base::RunLoop run_loop; + CloseObserver close_observer(&run_loop); + close_observer.Observe(receiver_window->web_contents()); + + CloseWindow(receiver_window.get()); + run_loop.Run(); + + destroyer.AwaitTerminate(std::move(receiver_window)); +}
diff --git a/chrome/browser/ui/media_router/presentation_receiver_window_delegate.h b/chrome/browser/ui/media_router/presentation_receiver_window_delegate.h new file mode 100644 index 0000000..358d31b --- /dev/null +++ b/chrome/browser/ui/media_router/presentation_receiver_window_delegate.h
@@ -0,0 +1,29 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_MEDIA_ROUTER_PRESENTATION_RECEIVER_WINDOW_DELEGATE_H_ +#define CHROME_BROWSER_UI_MEDIA_ROUTER_PRESENTATION_RECEIVER_WINDOW_DELEGATE_H_ + +namespace content { +class WebContents; +} + +// This interface allows communication between a PresentationReceiverWindow and +// its controller. The controller provides a WebContents instance for the +// window, and the window can tell the controller when it is closing. +class PresentationReceiverWindowDelegate { + public: + // WebContents instance provided by the delegate to be displayed in the + // window. + virtual content::WebContents* web_contents() const = 0; + + // Notifies the delegate that the window is closed so it can perform any + // necessary cleanup. + virtual void WindowClosed() = 0; + + protected: + ~PresentationReceiverWindowDelegate() = default; +}; + +#endif // CHROME_BROWSER_UI_MEDIA_ROUTER_PRESENTATION_RECEIVER_WINDOW_DELEGATE_H_
diff --git a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc index 930e24e..90edb88c 100644 --- a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc +++ b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
@@ -153,13 +153,7 @@ public content::NotificationObserver, public history::HistoryServiceObserver { public: - OmniboxViewTest() : observer_(this) {} - - // history::HisoryServiceObserver - void OnHistoryServiceLoaded( - history::HistoryService* history_service) override { - base::RunLoop::QuitCurrentWhenIdleDeprecated(); - } + OmniboxViewTest() {} protected: void SetUpOnMainThread() override { @@ -305,8 +299,9 @@ ASSERT_TRUE(history_service); if (!history_service->BackendLoaded()) { - observer_.Add(history_service); - content::RunMessageLoop(); + // Running the task scheduler until idle loads the history backend. + content::RunAllTasksUntilIdle(); + ASSERT_TRUE(history_service->BackendLoaded()); } BookmarkModel* bookmark_model = @@ -380,13 +375,9 @@ } private: - ScopedObserver<history::HistoryService, OmniboxViewTest> observer_; - DISALLOW_COPY_AND_ASSIGN(OmniboxViewTest); }; -// Currently all OmniboxViewTests are flaky (see https://crbug.com/751031). - // Test if ctrl-* accelerators are workable in omnibox. // See http://crbug.com/19193: omnibox blocks ctrl-* commands // @@ -458,7 +449,7 @@ #define MAYBE_PopupAccelerators PopupAccelerators #endif -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_PopupAccelerators) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_PopupAccelerators) { // Create a popup. Browser* popup = CreateBrowserForPopup(browser()->profile()); ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(popup)); @@ -514,7 +505,7 @@ #define MAYBE_BackspaceInKeywordMode BackspaceInKeywordMode #endif -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_BackspaceInKeywordMode) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_BackspaceInKeywordMode) { OmniboxView* omnibox_view = NULL; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); @@ -601,7 +592,7 @@ #define MAYBE_DesiredTLD DesiredTLD #endif -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_DesiredTLD) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_DesiredTLD) { OmniboxView* omnibox_view = NULL; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model(); @@ -633,7 +624,7 @@ #define MAYBE_DesiredTLDWithTemporaryText DesiredTLDWithTemporaryText #endif -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_DesiredTLDWithTemporaryText) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_DesiredTLDWithTemporaryText) { OmniboxView* omnibox_view = NULL; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model(); @@ -684,8 +675,7 @@ } // See http://crbug.com/431575. -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, - DISABLED_ClearUserTextAfterBackgroundCommit) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, ClearUserTextAfterBackgroundCommit) { OmniboxView* omnibox_view = NULL; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); @@ -714,7 +704,7 @@ EXPECT_EQ(ASCIIToUTF16(url2.spec()), omnibox_view->GetText()); } -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_AltEnter) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, AltEnter) { OmniboxView* omnibox_view = NULL; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); @@ -775,7 +765,7 @@ EXPECT_EQ("http://www.foo.com/search?q=z", url.spec()); } -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_EscapeToDefaultMatch) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, EscapeToDefaultMatch) { OmniboxView* omnibox_view = NULL; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model(); @@ -811,7 +801,7 @@ EXPECT_EQ(old_selected_line, popup_model->selected_line()); } -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_BasicTextOperations) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, BasicTextOperations) { ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)); chrome::FocusLocationBar(browser()); @@ -905,7 +895,7 @@ // Make sure the cursor position doesn't get set past the last character of // user input text when the URL is longer than the keyword. // (http://crbug.com/656209) -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_FocusSearchLongUrl) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, FocusSearchLongUrl) { OmniboxView* omnibox_view = NULL; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); @@ -919,8 +909,7 @@ // Make sure the display text is preserved when calling FocusSearch() when the // display text is not the permanent text. -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, - DISABLED_PreserveDisplayTextOnFocusSearch) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, PreserveDisplayTextOnFocusSearch) { OmniboxView* omnibox_view = NULL; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); @@ -972,8 +961,7 @@ EXPECT_EQ(19U, std::max(start, end)); } -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, - DISABLED_AcceptKeywordByTypingQuestionMark) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, AcceptKeywordByTypingQuestionMark) { OmniboxView* omnibox_view = NULL; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); @@ -1208,7 +1196,7 @@ ASSERT_TRUE(omnibox_view->GetText().empty()); } -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_NonSubstitutingKeywordTest) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, NonSubstitutingKeywordTest) { OmniboxView* omnibox_view = NULL; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model(); @@ -1259,7 +1247,13 @@ popup_model->result().default_match()->destination_url.spec()); } -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_DeleteItem) { +// crbug.com/751031 +#if defined(OS_MACOSX) +#define MAYBE_DeleteItem DISABLED_DeleteItem +#else +#define MAYBE_DeleteItem DeleteItem +#endif +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_DeleteItem) { // Disable the search provider, to make sure the popup contains only history // items. TemplateURLService* model = @@ -1365,7 +1359,7 @@ #define MAYBE_TabAcceptKeyword TabAcceptKeyword #endif -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_TabAcceptKeyword) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_TabAcceptKeyword) { OmniboxView* omnibox_view = NULL; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); @@ -1420,7 +1414,7 @@ #define MAYBE_TabTraverseResultsTest TabTraverseResultsTest #endif -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_TabTraverseResultsTest) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_TabTraverseResultsTest) { OmniboxView* omnibox_view = NULL; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model(); @@ -1513,8 +1507,7 @@ #define MAYBE_PersistKeywordModeOnTabSwitch PersistKeywordModeOnTabSwitch #endif -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, - DISABLED_PersistKeywordModeOnTabSwitch) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, MAYBE_PersistKeywordModeOnTabSwitch) { OmniboxView* omnibox_view = NULL; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); @@ -1562,7 +1555,7 @@ #endif IN_PROC_BROWSER_TEST_F(OmniboxViewTest, - DISABLED_CtrlKeyPressedWithInlineAutocompleteTest) { + MAYBE_CtrlKeyPressedWithInlineAutocompleteTest) { OmniboxView* omnibox_view = NULL; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model(); @@ -1585,7 +1578,7 @@ EXPECT_EQ(old_text, omnibox_view->GetText()); } -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_UndoRedo) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, UndoRedo) { ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)); chrome::FocusLocationBar(browser()); @@ -1654,8 +1647,7 @@ EXPECT_EQ(old_text, omnibox_view->GetText()); } -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, - DISABLED_BackspaceDeleteHalfWidthKatakana) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, BackspaceDeleteHalfWidthKatakana) { OmniboxView* omnibox_view = NULL; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); // Insert text: ダ. This is two, 3-byte UTF-8 characters: @@ -1681,8 +1673,7 @@ #endif } -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, - DISABLED_DoesNotUpdateAutocompleteOnBlur) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DoesNotUpdateAutocompleteOnBlur) { OmniboxView* omnibox_view = NULL; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model(); @@ -1706,7 +1697,7 @@ omnibox_view->model()->autocomplete_controller()->input_.text()); } -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_Paste) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, Paste) { OmniboxView* omnibox_view = NULL; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model(); @@ -1747,7 +1738,7 @@ // TODO(msw): Test that AltGr+V does not paste. } -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_CopyURLToClipboard) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, CopyURLToClipboard) { // Set permanent text thus making sure that omnibox treats 'google.com' // as URL (not as ordinary user input). OmniboxView* omnibox_view = NULL; @@ -1780,7 +1771,9 @@ ui::Clipboard::GetHtmlFormatType(), ui::CLIPBOARD_TYPE_COPY_PASTE)); // Windows clipboard only supports text URLs. -#if defined(OS_LINUX) || defined(OS_MACOSX) +// Mac clipboard not reporting URL format available for some reason. +// crbug.com/751031 +#if defined(OS_LINUX) EXPECT_TRUE(clipboard->IsFormatAvailable(ui::Clipboard::GetUrlFormatType(), ui::CLIPBOARD_TYPE_COPY_PASTE)); #endif @@ -1790,7 +1783,7 @@ EXPECT_EQ(target_url, url); } -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_CutURLToClipboard) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, CutURLToClipboard) { // Set permanent text thus making sure that omnibox treats 'google.com' // as URL (not as ordinary user input). OmniboxView* omnibox_view = NULL; @@ -1823,7 +1816,9 @@ ui::Clipboard::GetHtmlFormatType(), ui::CLIPBOARD_TYPE_COPY_PASTE)); // Windows clipboard only supports text URLs. -#if defined(OS_LINUX) || defined(OS_MACOSX) +// Mac clipboard not reporting URL format available for some reason. +// crbug.com/751031 +#if defined(OS_LINUX) EXPECT_TRUE(clipboard->IsFormatAvailable(ui::Clipboard::GetUrlFormatType(), ui::CLIPBOARD_TYPE_COPY_PASTE)); #endif @@ -1833,7 +1828,7 @@ EXPECT_EQ(target_url, url); } -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_CopyTextToClipboard) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, CopyTextToClipboard) { OmniboxView* omnibox_view = NULL; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); const char* target_text = "foo"; @@ -1856,7 +1851,7 @@ EXPECT_EQ(ASCIIToUTF16(target_text), omnibox_view->GetText()); } -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_CutTextToClipboard) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, CutTextToClipboard) { OmniboxView* omnibox_view = NULL; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); const char* target_text = "foo"; @@ -1879,7 +1874,7 @@ EXPECT_EQ(base::string16(), omnibox_view->GetText()); } -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_EditSearchEngines) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, EditSearchEngines) { OmniboxView* omnibox_view = nullptr; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); #if defined(OS_CHROMEOS) @@ -1901,8 +1896,7 @@ EXPECT_FALSE(omnibox_view->model()->popup_model()->IsOpen()); } -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, - DISABLED_CtrlArrowAfterArrowSuggestions) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, CtrlArrowAfterArrowSuggestions) { OmniboxView* omnibox_view = NULL; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model(); @@ -1952,7 +1946,7 @@ // Test that if the Omnibox has focus, and had everything selected before a // non-user-initiated update, then it retains the selection after the update. -IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DISABLED_SelectAllStaysAfterUpdate) { +IN_PROC_BROWSER_TEST_F(OmniboxViewTest, SelectAllStaysAfterUpdate) { OmniboxView* omnibox_view = nullptr; ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view)); TestToolbarModel* test_toolbar_model = new TestToolbarModel;
diff --git a/chrome/browser/ui/passwords/manage_passwords_test.cc b/chrome/browser/ui/passwords/manage_passwords_test.cc index 50f04f5..86581ee 100644 --- a/chrome/browser/ui/passwords/manage_passwords_test.cc +++ b/chrome/browser/ui/passwords/manage_passwords_test.cc
@@ -56,7 +56,7 @@ // Show the window to ensure that it's active. browser()->window()->Show(); - CommandUpdater* updater = browser()->command_controller()->command_updater(); + CommandUpdater* updater = browser()->command_controller(); EXPECT_TRUE(updater->IsCommandEnabled(IDC_MANAGE_PASSWORDS_FOR_PAGE)); EXPECT_TRUE(updater->ExecuteCommand(IDC_MANAGE_PASSWORDS_FOR_PAGE));
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc index dced1dc..6c70cac 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/password_manager/chrome_password_manager_client.h" #include "chrome/browser/password_manager/password_store_factory.h" #include "chrome/browser/ui/browser_command_controller.h" +#include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_navigator_params.h" #include "chrome/browser/ui/browser_window.h" @@ -579,8 +580,7 @@ if (!browser || browser->toolbar_model()->input_in_progress()) return; - CommandUpdater* updater = browser->command_controller()->command_updater(); - updater->ExecuteCommand(IDC_MANAGE_PASSWORDS_FOR_PAGE); + chrome::ExecuteCommand(browser, IDC_MANAGE_PASSWORDS_FOR_PAGE); } void ManagePasswordsUIController::DestroyAccountChooser() {
diff --git a/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc b/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc index e9eeb46..ca3ad344 100644 --- a/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc +++ b/chrome/browser/ui/toolbar/media_router_contextual_menu_unittest.cc
@@ -8,6 +8,7 @@ #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/extensions/browser_action_test_util.h" #include "chrome/browser/extensions/extension_action_test_util.h" +#include "chrome/browser/extensions/load_error_reporter.h" #include "chrome/browser/signin/fake_signin_manager_builder.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/ui/toolbar/component_toolbar_actions_factory.h" @@ -38,7 +39,7 @@ void SetUp() override { BrowserWithTestWindowTest::SetUp(); - ExtensionErrorReporter::Init(true); + extensions::LoadErrorReporter::Init(true); toolbar_actions_model_ = extensions::extension_action_test_util::CreateToolbarModelForProfile(
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc b/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc index ce3e9fc..db13f79 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc +++ b/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/extensions/extension_action_manager.h" #include "chrome/browser/extensions/extension_action_test_util.h" #include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/load_error_reporter.h" #include "chrome/browser/extensions/test_extension_dir.h" #include "chrome/browser/extensions/test_extension_system.h" #include "chrome/browser/extensions/unpacked_installer.h" @@ -110,11 +111,12 @@ // The ToolbarActionErrorTestObserver is used to notify when an extension // failed to load. -class ToolbarActionErrorTestObserver : public ExtensionErrorReporter::Observer { +class ToolbarActionErrorTestObserver + : public extensions::LoadErrorReporter::Observer { public: ToolbarActionErrorTestObserver() : extension_error_reporter_observer_(this) { extension_error_reporter_observer_.Add( - ExtensionErrorReporter::GetInstance()); + extensions::LoadErrorReporter::GetInstance()); } ~ToolbarActionErrorTestObserver() override {} @@ -122,7 +124,7 @@ void WaitForOnLoadFailure() { run_loop_.Run(); } private: - // ExtensionErrorReporter::Observer: + // extensions::LoadErrorReporter::Observer: void OnLoadFailure(content::BrowserContext* browser_context, const base::FilePath& extension_path, const std::string& error) override { @@ -131,7 +133,8 @@ base::RunLoop run_loop_; - ScopedObserver<ExtensionErrorReporter, ExtensionErrorReporter::Observer> + ScopedObserver<extensions::LoadErrorReporter, + extensions::LoadErrorReporter::Observer> extension_error_reporter_observer_; DISALLOW_COPY_AND_ASSIGN(ToolbarActionErrorTestObserver); @@ -146,7 +149,7 @@ void ToolbarActionsBarUnitTest::SetUp() { BrowserWithTestWindowTest::SetUp(); - ExtensionErrorReporter::Init(true); + extensions::LoadErrorReporter::Init(true); // The toolbar typically displays extension icons, so create some extension // test infrastructure.
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model.cc b/chrome/browser/ui/toolbar/toolbar_actions_model.cc index a29ce30..abb5c64 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_model.cc +++ b/chrome/browser/ui/toolbar/toolbar_actions_model.cc
@@ -56,7 +56,7 @@ has_active_bubble_(false), extension_action_observer_(this), extension_registry_observer_(this), - extension_error_reporter_observer_(this), + load_error_reporter_observer_(this), weak_ptr_factory_(this) { extensions::ExtensionSystem::Get(profile_)->ready().Post( FROM_HERE, base::Bind(&ToolbarActionsModel::OnReady, @@ -256,7 +256,8 @@ void ToolbarActionsModel::OnReady() { InitializeActionList(); - extension_error_reporter_observer_.Add(ExtensionErrorReporter::GetInstance()); + load_error_reporter_observer_.Add( + extensions::LoadErrorReporter::GetInstance()); // Wait until the extension system is ready before observing any further // changes so that the toolbar buttons can be shown in their stable ordering
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_model.h b/chrome/browser/ui/toolbar/toolbar_actions_model.h index 4eb179b..226af14 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_model.h +++ b/chrome/browser/ui/toolbar/toolbar_actions_model.h
@@ -13,7 +13,7 @@ #include "base/scoped_observer.h" #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" #include "chrome/browser/extensions/extension_action.h" -#include "chrome/browser/extensions/extension_error_reporter.h" +#include "chrome/browser/extensions/load_error_reporter.h" #include "chrome/browser/ui/toolbar/component_action_delegate.h" #include "components/keyed_service/core/keyed_service.h" #include "components/prefs/pref_change_registrar.h" @@ -42,7 +42,7 @@ // actions in a particular window should check that window's instance of // ToolbarActionsBar, which is responsible for the per-window layout. class ToolbarActionsModel : public extensions::ExtensionActionAPI::Observer, - public ExtensionErrorReporter::Observer, + public extensions::LoadErrorReporter::Observer, public extensions::ExtensionRegistryObserver, public KeyedService, public ComponentActionDelegate { @@ -232,7 +232,7 @@ content::WebContents* web_contents, content::BrowserContext* browser_context) override; - // ExtensionErrorReporter::Observer: + // extensions::LoadErrorReporter::Observer: void OnLoadFailure(content::BrowserContext* browser_context, const base::FilePath& extension_path, const std::string& error) override; @@ -346,8 +346,9 @@ PrefChangeRegistrar pref_change_registrar_; base::Closure pref_change_callback_; - ScopedObserver<ExtensionErrorReporter, ExtensionErrorReporter::Observer> - extension_error_reporter_observer_; + ScopedObserver<extensions::LoadErrorReporter, + extensions::LoadErrorReporter::Observer> + load_error_reporter_observer_; base::WeakPtrFactory<ToolbarActionsModel> weak_ptr_factory_;
diff --git a/chrome/browser/ui/views/accessibility/invert_bubble_view.cc b/chrome/browser/ui/views/accessibility/invert_bubble_view.cc index 35421ac..c1938825 100644 --- a/chrome/browser/ui/views/accessibility/invert_bubble_view.cc +++ b/chrome/browser/ui/views/accessibility/invert_bubble_view.cc
@@ -113,7 +113,8 @@ close_->SetFontList(original_font_list); close_->set_listener(this); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); views::ColumnSet* columns = layout->AddColumnSet(0); for (int i = 0; i < 4; i++) {
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_panel.cc index 70dc993..039cf310 100644 --- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_panel.cc +++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_panel.cc
@@ -90,7 +90,7 @@ class BulletedPermissionsList : public views::View { public: BulletedPermissionsList() { - layout_ = views::GridLayout::CreateAndInstall(this); + layout_ = SetLayoutManager(std::make_unique<views::GridLayout>(this)); // Create 3 columns: the bullet, the bullet text, and the revoke button. views::ColumnSet* column_set = layout_->AddColumnSet(kBulletColumnSetId);
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc index 91f19d9..7abeb9a 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
@@ -277,7 +277,8 @@ SetLayoutManager(std::make_unique<views::FillLayout>()); bookmark_contents_view_ = new views::View(); - GridLayout* layout = GridLayout::CreateAndInstall(bookmark_contents_view_); + GridLayout* layout = bookmark_contents_view_->SetLayoutManager( + std::make_unique<views::GridLayout>(bookmark_contents_view_)); constexpr int kColumnId = 0; ConfigureTextfieldStack(layout, kColumnId);
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc index 37b39b2..04c97be 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_editor_view.cc
@@ -336,7 +336,8 @@ new_folder_button_->SetEnabled(false); } - GridLayout* layout = GridLayout::CreateAndInstall(this); + GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); const int labels_column_set_id = 0;
diff --git a/chrome/browser/ui/views/certificate_selector.cc b/chrome/browser/ui/views/certificate_selector.cc index 91d52bb..3c269244 100644 --- a/chrome/browser/ui/views/certificate_selector.cc +++ b/chrome/browser/ui/views/certificate_selector.cc
@@ -200,7 +200,8 @@ void CertificateSelector::InitWithText( std::unique_ptr<views::View> text_label) { - views::GridLayout* const layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* const layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); const int kColumnSetId = 0; views::ColumnSet* const column_set = layout->AddColumnSet(kColumnSetId);
diff --git a/chrome/browser/ui/views/collected_cookies_views.cc b/chrome/browser/ui/views/collected_cookies_views.cc index f142b72f8..74c2217 100644 --- a/chrome/browser/ui/views/collected_cookies_views.cc +++ b/chrome/browser/ui/views/collected_cookies_views.cc
@@ -397,7 +397,8 @@ void CollectedCookiesViews::Init() { using views::GridLayout; - GridLayout* layout = GridLayout::CreateAndInstall(this); + GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); if (provider->UseExtraDialogPadding()) { SetBorder( @@ -472,7 +473,9 @@ using views::GridLayout; views::View* pane = new views::View(); - GridLayout* layout = GridLayout::CreateAndInstall(pane); + GridLayout* layout = + pane->SetLayoutManager(std::make_unique<views::GridLayout>(pane)); + pane->SetBorder( views::CreateEmptyBorder(ChromeLayoutProvider::Get()->GetInsetsMetric( views::INSETS_DIALOG_SUBSECTION))); @@ -535,7 +538,8 @@ using views::GridLayout; views::View* pane = new views::View(); - GridLayout* layout = GridLayout::CreateAndInstall(pane); + GridLayout* layout = + pane->SetLayoutManager(std::make_unique<views::GridLayout>(pane)); pane->SetBorder( views::CreateEmptyBorder(ChromeLayoutProvider::Get()->GetInsetsMetric( views::INSETS_DIALOG_SUBSECTION))); @@ -567,8 +571,8 @@ { auto allowed = std::make_unique<views::View>(); - views::GridLayout* layout = - views::GridLayout::CreateAndInstall(allowed.get()); + views::GridLayout* layout = allowed->SetLayoutManager( + std::make_unique<views::GridLayout>(allowed.get())); block_allowed_button_ = views::MdTextButton::CreateSecondaryUiButton( this, l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_BLOCK_BUTTON)); @@ -584,8 +588,8 @@ { auto blocked = std::make_unique<views::View>(); - views::GridLayout* layout = - views::GridLayout::CreateAndInstall(blocked.get()); + views::GridLayout* layout = blocked->SetLayoutManager( + std::make_unique<views::GridLayout>(blocked.get())); blocked->SetVisible(false); allow_blocked_button_ = views::MdTextButton::CreateSecondaryUiButton(
diff --git a/chrome/browser/ui/views/confirm_bubble_views.cc b/chrome/browser/ui/views/confirm_bubble_views.cc index 82a52d46..483334e 100644 --- a/chrome/browser/ui/views/confirm_bubble_views.cc +++ b/chrome/browser/ui/views/confirm_bubble_views.cc
@@ -22,7 +22,8 @@ : model_(std::move(model)), link_(NULL) { set_margins(ChromeLayoutProvider::Get()->GetDialogInsetsForContentType( views::TEXT, views::TEXT)); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); // Use a fixed maximum message width, so longer messages will wrap. const int kMaxMessageWidth = 400;
diff --git a/chrome/browser/ui/views/content_setting_bubble_contents.cc b/chrome/browser/ui/views/content_setting_bubble_contents.cc index a17121d..827f1bf 100644 --- a/chrome/browser/ui/views/content_setting_bubble_contents.cc +++ b/chrome/browser/ui/views/content_setting_bubble_contents.cc
@@ -252,7 +252,8 @@ void ContentSettingBubbleContents::ListItemContainer::ResetLayout() { using views::GridLayout; - GridLayout* layout = GridLayout::CreateAndInstall(this); + GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); views::ColumnSet* item_list_column_set = layout->AddColumnSet(0); item_list_column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 0, GridLayout::USE_PREF, 0, 0); @@ -377,7 +378,8 @@ void ContentSettingBubbleContents::Init() { using views::GridLayout; - GridLayout* layout = views::GridLayout::CreateAndInstall(this); + GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); const ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); const int related_control_horizontal_spacing = provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_HORIZONTAL);
diff --git a/chrome/browser/ui/views/cookie_info_view.cc b/chrome/browser/ui/views/cookie_info_view.cc index 799ab4e..6763a19 100644 --- a/chrome/browser/ui/views/cookie_info_view.cc +++ b/chrome/browser/ui/views/cookie_info_view.cc
@@ -148,7 +148,8 @@ l10n_util::GetStringUTF16(IDS_COOKIES_COOKIE_EXPIRES_LABEL)); expires_value_field_ = new views::Textfield; - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); const gfx::Insets& dialog_insets = provider->GetInsetsMetric(views::INSETS_DIALOG);
diff --git a/chrome/browser/ui/views/create_application_shortcut_view.cc b/chrome/browser/ui/views/create_application_shortcut_view.cc index eb5afb0..5914b70 100644 --- a/chrome/browser/ui/views/create_application_shortcut_view.cc +++ b/chrome/browser/ui/views/create_application_shortcut_view.cc
@@ -106,7 +106,8 @@ ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); // Layout controls - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); static const int kHeaderColumnSetId = 0; views::ColumnSet* column_set = layout->AddColumnSet(kHeaderColumnSetId);
diff --git a/chrome/browser/ui/views/crypto_module_password_dialog_view.cc b/chrome/browser/ui/views/crypto_module_password_dialog_view.cc index 70d3a1c..d307e54b 100644 --- a/chrome/browser/ui/views/crypto_module_password_dialog_view.cc +++ b/chrome/browser/ui/views/crypto_module_password_dialog_view.cc
@@ -125,7 +125,8 @@ ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); views::ColumnSet* reason_column_set = layout->AddColumnSet(0); reason_column_set->AddColumn(
diff --git a/chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_bubble_view.cc b/chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_bubble_view.cc index 0639acf..9df9f36 100644 --- a/chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_bubble_view.cc +++ b/chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_bubble_view.cc
@@ -40,7 +40,8 @@ base::MakeUnique<DesktopIOSPromotionBubbleController>(profile, this, entry_point)) { - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); SetBorder(views::CreateEmptyBorder( 0,
diff --git a/chrome/browser/ui/views/download/download_danger_prompt_views.cc b/chrome/browser/ui/views/download/download_danger_prompt_views.cc index d004b1e..23b28c7 100644 --- a/chrome/browser/ui/views/download/download_danger_prompt_views.cc +++ b/chrome/browser/ui/views/download/download_danger_prompt_views.cc
@@ -98,8 +98,8 @@ set_margins(ChromeLayoutProvider::Get()->GetDialogInsetsForContentType( views::TEXT, views::TEXT)); - views::GridLayout* layout = - views::GridLayout::CreateAndInstall(contents_view_); + views::GridLayout* layout = contents_view_->SetLayoutManager( + std::make_unique<views::GridLayout>(contents_view_)); views::ColumnSet* column_set = layout->AddColumnSet(0); column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
diff --git a/chrome/browser/ui/views/extensions/bookmark_app_confirmation_view.cc b/chrome/browser/ui/views/extensions/bookmark_app_confirmation_view.cc index 7cc3456..130ff981 100644 --- a/chrome/browser/ui/views/extensions/bookmark_app_confirmation_view.cc +++ b/chrome/browser/ui/views/extensions/bookmark_app_confirmation_view.cc
@@ -43,7 +43,8 @@ const ChromeLayoutProvider* layout_provider = ChromeLayoutProvider::Get(); set_margins(layout_provider->GetDialogInsetsForContentType(views::CONTROL, views::CONTROL)); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); constexpr int kColumnSetId = 0; views::ColumnSet* column_set = layout->AddColumnSet(kColumnSetId);
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc index 65673b2..62bf733 100644 --- a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc +++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
@@ -222,7 +222,8 @@ } // namespace BulletedView::BulletedView(views::View* view) { - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); views::ColumnSet* column_set = layout->AddColumnSet(0); column_set->AddColumn(views::GridLayout::CENTER, views::GridLayout::LEADING, 0, views::GridLayout::FIXED, kBulletWidth, 0); @@ -347,8 +348,8 @@ // Create the scrollable view which will contain the permissions and retained // files/devices. It will span the full content width. CustomScrollableView* scrollable = new CustomScrollableView(); - views::GridLayout* scroll_layout = - views::GridLayout::CreateAndInstall(scrollable); + views::GridLayout* scroll_layout = scrollable->SetLayoutManager( + std::make_unique<views::GridLayout>(scrollable)); views::ColumnSet* scrollable_column_set = scroll_layout->AddColumnSet(column_set_id); @@ -518,7 +519,8 @@ // extension icon can be shown on the right of the dialog title, but on the // same y-axis, and the scroll view used to contain other content can have its // scrollbar aligned with the right edge of the dialog. - views::GridLayout* layout = views::GridLayout::CreateAndInstall(container_); + views::GridLayout* layout = container_->SetLayoutManager( + std::make_unique<views::GridLayout>(container_)); container_->SetBorder(views::CreateEmptyBorder(0, content_insets.left(), content_insets.bottom(), 0)); AddChildView(container_); @@ -729,7 +731,8 @@ expanded_(false) { DCHECK(!details.empty()); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); constexpr int kColumnSetId = 0; views::ColumnSet* column_set = layout->AddColumnSet(kColumnSetId);
diff --git a/chrome/browser/ui/views/extensions/extension_popup.cc b/chrome/browser/ui/views/extensions/extension_popup.cc index deadc4eb..4582862a 100644 --- a/chrome/browser/ui/views/extensions/extension_popup.cc +++ b/chrome/browser/ui/views/extensions/extension_popup.cc
@@ -128,9 +128,7 @@ content::DevToolsAgentHost* agent_host) { if (host()->host_contents() != agent_host->GetWebContents()) return; - // Widget::Close posts a task, which should give the devtools window a - // chance to finish detaching from the inspected RenderViewHost. - GetWidget()->Close(); + inspect_with_devtools_ = false; } void ExtensionPopup::OnExtensionSizeChanged(ExtensionViewViews* view) {
diff --git a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc index 512b820..9e3de29 100644 --- a/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc +++ b/chrome/browser/ui/views/extensions/media_galleries_dialog_views.cc
@@ -103,7 +103,8 @@ const int dialog_content_width = views::Widget::GetLocalizedContentsWidth( IDS_MEDIA_GALLERIES_DIALOG_CONTENT_WIDTH_CHARS); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(contents_); + views::GridLayout* layout = contents_->SetLayoutManager( + std::make_unique<views::GridLayout>(contents_)); int column_set_id = 0; views::ColumnSet* columns = layout->AddColumnSet(column_set_id);
diff --git a/chrome/browser/ui/views/first_run_bubble.cc b/chrome/browser/ui/views/first_run_bubble.cc index 35c67d3..643f7c8 100644 --- a/chrome/browser/ui/views/first_run_bubble.cc +++ b/chrome/browser/ui/views/first_run_bubble.cc
@@ -70,7 +70,8 @@ views::Label* subtext = new views::Label( l10n_util::GetStringUTF16(IDS_FR_BUBBLE_SUBTEXT), {original_font_list}); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
diff --git a/chrome/browser/ui/views/first_run_dialog.cc b/chrome/browser/ui/views/first_run_dialog.cc index 1607aaa..68d39c0 100644 --- a/chrome/browser/ui/views/first_run_dialog.cc +++ b/chrome/browser/ui/views/first_run_dialog.cc
@@ -72,7 +72,8 @@ report_crashes_(NULL) { set_margins(ChromeLayoutProvider::Get()->GetDialogInsetsForContentType( views::CONTROL, views::CONTROL)); - GridLayout* layout = GridLayout::CreateAndInstall(this); + GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); views::ColumnSet* column_set = layout->AddColumnSet(0); column_set->AddColumn(GridLayout::FILL, GridLayout::CENTER, 0,
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc index d150b25..1ba79a573 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -386,7 +386,7 @@ void RunTest(int command, int expected_index) { reveal_started_ = reveal_ended_ = false; expected_index_ = expected_index; - browser()->command_controller()->command_updater()->ExecuteCommand(command); + browser()->command_controller()->ExecuteCommand(command); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(reveal_ended_); }
diff --git a/chrome/browser/ui/views/global_error_bubble_view.cc b/chrome/browser/ui/views/global_error_bubble_view.cc index 3d16cba..0ab95a5 100644 --- a/chrome/browser/ui/views/global_error_bubble_view.cc +++ b/chrome/browser/ui/views/global_error_bubble_view.cc
@@ -116,7 +116,8 @@ message_labels.push_back(message_label); } - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); // First row, message labels. views::ColumnSet* cs = layout->AddColumnSet(0);
diff --git a/chrome/browser/ui/views/harmony/bulleted_label_list_view.cc b/chrome/browser/ui/views/harmony/bulleted_label_list_view.cc index 2f80b01..8b6b3d68 100644 --- a/chrome/browser/ui/views/harmony/bulleted_label_list_view.cc +++ b/chrome/browser/ui/views/harmony/bulleted_label_list_view.cc
@@ -52,7 +52,8 @@ constexpr auto USE_PREF = views::GridLayout::USE_PREF; constexpr auto FIXED = views::GridLayout::FIXED; - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); views::ColumnSet* columns = layout->AddColumnSet(kColumnSetId); int width = ChromeLayoutProvider::Get()->GetDistanceMetric(
diff --git a/chrome/browser/ui/views/hover_button.cc b/chrome/browser/ui/views/hover_button.cc index 23cbc1c..d72687c 100644 --- a/chrome/browser/ui/views/hover_button.cc +++ b/chrome/browser/ui/views/hover_button.cc
@@ -120,7 +120,8 @@ SetBorder(CreateBorderWithVerticalSpacing(remaining_vert_spacing)); - views::GridLayout* grid_layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* grid_layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); // Badging may make the icon slightly wider (but not taller). However, the // layout should be the same whether or not the icon is badged, so allow the // badged part of the icon to extend into the padding.
diff --git a/chrome/browser/ui/views/hung_renderer_view.cc b/chrome/browser/ui/views/hung_renderer_view.cc index 49b6f64..c740c91 100644 --- a/chrome/browser/ui/views/hung_renderer_view.cc +++ b/chrome/browser/ui/views/hung_renderer_view.cc
@@ -448,7 +448,8 @@ using views::GridLayout; - GridLayout* layout = GridLayout::CreateAndInstall(this); + GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); constexpr int kColumnSetId = 0;
diff --git a/chrome/browser/ui/views/ime/ime_warning_bubble_view.cc b/chrome/browser/ui/views/ime/ime_warning_bubble_view.cc index a4f7893..5d3b2e1 100644 --- a/chrome/browser/ui/views/ime/ime_warning_bubble_view.cc +++ b/chrome/browser/ui/views/ime/ime_warning_bubble_view.cc
@@ -159,7 +159,8 @@ // ----------------------------------------- // - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); int cs_id = 0;
diff --git a/chrome/browser/ui/views/ime/input_ime_apitest_nonchromeos.cc b/chrome/browser/ui/views/ime/input_ime_apitest_nonchromeos.cc index 267de80..6d584a0 100644 --- a/chrome/browser/ui/views/ime/input_ime_apitest_nonchromeos.cc +++ b/chrome/browser/ui/views/ime/input_ime_apitest_nonchromeos.cc
@@ -4,6 +4,7 @@ #include "base/auto_reset.h" #include "base/strings/utf_string_conversions.h" +#include "build/build_config.h" #include "chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/ui/browser_window.h" @@ -111,7 +112,12 @@ input_method->DetachTextInputClient(client2.get()); } +// TODO(https://crbug.com/795631): This test is failing on the Linux bot. +#if defined(OS_LINUX) +IN_PROC_BROWSER_TEST_F(InputImeApiTest, DISABLED_SendKeyEventsOnNormalPage) { +#else IN_PROC_BROWSER_TEST_F(InputImeApiTest, SendKeyEventsOnNormalPage) { +#endif // Navigates to special page that sendKeyEvents API has limition with. ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); // Manipulates the focused text input client because the follow cursor
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view.cc b/chrome/browser/ui/views/intent_picker_bubble_view.cc index 57f478f..29c2ac4 100644 --- a/chrome/browser/ui/views/intent_picker_bubble_view.cc +++ b/chrome/browser/ui/views/intent_picker_bubble_view.cc
@@ -211,7 +211,8 @@ } void IntentPickerBubbleView::Init() { - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); // Creates a view to hold the views for each app. views::View* scrollable_view = new views::View();
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc index 75c69a7..961511c3 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -239,14 +239,17 @@ add_icon(zoom_view_ = new ZoomView(delegate_)); add_icon(manage_passwords_icon_view_ = new ManagePasswordsIconViews(command_updater())); - add_icon(save_credit_card_icon_view_ = - new autofill::SaveCardIconView(command_updater(), browser_)); + if (browser_) + add_icon(save_credit_card_icon_view_ = + new autofill::SaveCardIconView(command_updater(), browser_)); add_icon(translate_icon_view_ = new TranslateIconView(command_updater())); #if defined(OS_CHROMEOS) - add_icon(intent_picker_view_ = new IntentPickerView(browser_)); + if (browser_) + add_icon(intent_picker_view_ = new IntentPickerView(browser_)); #endif add_icon(find_bar_icon_ = new FindBarIcon()); - add_icon(star_view_ = new StarView(command_updater(), browser_)); + if (browser_) + add_icon(star_view_ = new StarView(command_updater(), browser_)); clear_all_button_ = views::CreateVectorImageButton(this); clear_all_button_->SetTooltipText( @@ -449,10 +452,12 @@ // Compute width of omnibox-trailing content. int trailing_width = edge_thickness; - trailing_width += IncrementalMinimumWidth(star_view_) + - IncrementalMinimumWidth(translate_icon_view_) + - IncrementalMinimumWidth(save_credit_card_icon_view_) + - IncrementalMinimumWidth(manage_passwords_icon_view_) + + if (star_view_) + trailing_width += IncrementalMinimumWidth(star_view_); + trailing_width += IncrementalMinimumWidth(translate_icon_view_); + if (save_credit_card_icon_view_) + trailing_width += IncrementalMinimumWidth(save_credit_card_icon_view_); + trailing_width += IncrementalMinimumWidth(manage_passwords_icon_view_) + IncrementalMinimumWidth(zoom_view_); #if defined(OS_CHROMEOS) if (intent_picker_view_) @@ -535,12 +540,15 @@ }; #if defined(OS_CHROMEOS) - add_trailing_decoration(intent_picker_view_); + if (intent_picker_view_) + add_trailing_decoration(intent_picker_view_); #endif - add_trailing_decoration(star_view_); + if (star_view_) + add_trailing_decoration(star_view_); add_trailing_decoration(find_bar_icon_); add_trailing_decoration(translate_icon_view_); - add_trailing_decoration(save_credit_card_icon_view_); + if (save_credit_card_icon_view_) + add_trailing_decoration(save_credit_card_icon_view_); add_trailing_decoration(manage_passwords_icon_view_); add_trailing_decoration(zoom_view_); for (ContentSettingViews::const_reverse_iterator i( @@ -768,7 +776,7 @@ bool LocationBarView::RefreshSaveCreditCardIconView() { WebContents* web_contents = GetWebContents(); - if (!web_contents) + if (!save_credit_card_icon_view_ || !web_contents) return false; const bool was_visible = save_credit_card_icon_view_->visible(); @@ -776,8 +784,11 @@ autofill::SaveCardBubbleControllerImpl* controller = autofill::SaveCardBubbleControllerImpl::FromWebContents(web_contents); bool enabled = controller && controller->IsIconVisible(); - command_updater()->UpdateCommandEnabled(IDC_SAVE_CREDIT_CARD_FOR_PAGE, - enabled); + if (!command_updater()->UpdateCommandEnabled( + IDC_SAVE_CREDIT_CARD_FOR_PAGE, enabled)) { + enabled = enabled && command_updater()->IsCommandEnabled( + IDC_SAVE_CREDIT_CARD_FOR_PAGE); + } save_credit_card_icon_view_->SetVisible(enabled); return was_visible != save_credit_card_icon_view_->visible(); @@ -804,7 +815,10 @@ translate::LanguageState& language_state = ChromeTranslateClient::FromWebContents(web_contents)->GetLanguageState(); bool enabled = language_state.translate_enabled(); - command_updater()->UpdateCommandEnabled(IDC_TRANSLATE_PAGE, enabled); + if (!command_updater()->UpdateCommandEnabled(IDC_TRANSLATE_PAGE, enabled)) { + enabled = enabled && command_updater()->IsCommandEnabled( + IDC_TRANSLATE_PAGE); + } translate_icon_view_->SetVisible(enabled); if (!enabled) TranslateBubbleView::CloseCurrentBubble();
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h index 65cae40..c8c8d46 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_view.h +++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -153,14 +153,16 @@ void SetStarToggled(bool on); #if defined(OS_CHROMEOS) - // The intent picker, should not always be visible. + // The intent picker, should not always be visible. It will be null when + // |browser_| is null. IntentPickerView* intent_picker_view() { return intent_picker_view_; } #endif // defined(OS_CHROMEOS) - // The star. It may not be visible. + // The star. It may not be visible. It will be null when |browser_| is null. StarView* star_view() { return star_view_; } - // The save credit card icon. It may not be visible. + // The save credit card icon. It may not be visible. It will be null when + // |browser_| is null. autofill::SaveCardIconView* save_credit_card_icon_view() { return save_credit_card_icon_view_; } @@ -402,21 +404,22 @@ // The manage passwords icon. ManagePasswordsIconViews* manage_passwords_icon_view_ = nullptr; - // The save credit card icon. + // The save credit card icon. It will be null when |browser_| is null. autofill::SaveCardIconView* save_credit_card_icon_view_ = nullptr; // The icon for Translate. TranslateIconView* translate_icon_view_ = nullptr; #if defined(OS_CHROMEOS) - // The intent picker for accessing ARC's apps. + // The intent picker for accessing ARC's apps. It will be null when + // |browser_| is null. IntentPickerView* intent_picker_view_ = nullptr; #endif // defined(OS_CHROMEOS) // The icon displayed when the find bar is visible. FindBarIcon* find_bar_icon_ = nullptr; - // The star for bookmarking. + // The star for bookmarking. It will be null when |browser_| is null. StarView* star_view_ = nullptr; // An [x] that appears in touch mode (when the OSK is visible) and allows the
diff --git a/chrome/browser/ui/views/login_view.cc b/chrome/browser/ui/views/login_view.cc index 541a03b..23c10bc 100644 --- a/chrome/browser/ui/views/login_view.cc +++ b/chrome/browser/ui/views/login_view.cc
@@ -53,7 +53,8 @@ provider->GetDialogInsetsForContentType(views::TEXT, views::CONTROL))); // Initialize the Grid Layout Manager used for this dialog box. - GridLayout* layout = GridLayout::CreateAndInstall(this); + GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); views::ColumnSet* column_set = layout->AddColumnSet(kHeaderColumnSetId); column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, kStretchy, GridLayout::FIXED, kMessageWidth, 0);
diff --git a/chrome/browser/ui/views/media_router/presentation_receiver_window_factory.cc b/chrome/browser/ui/views/media_router/presentation_receiver_window_factory.cc new file mode 100644 index 0000000..eddcc2b --- /dev/null +++ b/chrome/browser/ui/views/media_router/presentation_receiver_window_factory.cc
@@ -0,0 +1,29 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/media_router/presentation_receiver_window.h" + +#include <memory> + +#include "base/logging.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/media_router/presentation_receiver_window_delegate.h" +#include "chrome/browser/ui/views/media_router/presentation_receiver_window_frame.h" +#include "chrome/browser/ui/views/media_router/presentation_receiver_window_view.h" +#include "content/public/browser/web_contents.h" + +// static +PresentationReceiverWindow* PresentationReceiverWindow::Create( + PresentationReceiverWindowDelegate* delegate, + const gfx::Rect& bounds) { + DCHECK(delegate); + DCHECK(delegate->web_contents()); + auto* frame = new PresentationReceiverWindowFrame(Profile::FromBrowserContext( + delegate->web_contents()->GetBrowserContext())); + auto view = std::make_unique<PresentationReceiverWindowView>(frame, delegate); + auto* view_raw = view.get(); + frame->InitReceiverFrame(std::move(view), bounds); + view_raw->Init(); + return view_raw; +}
diff --git a/chrome/browser/ui/views/media_router/presentation_receiver_window_frame.cc b/chrome/browser/ui/views/media_router/presentation_receiver_window_frame.cc new file mode 100644 index 0000000..7a1fe6c --- /dev/null +++ b/chrome/browser/ui/views/media_router/presentation_receiver_window_frame.cc
@@ -0,0 +1,28 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/media_router/presentation_receiver_window_frame.h" + +#include "chrome/browser/themes/theme_service.h" +#include "ui/views/widget/widget_delegate.h" + +PresentationReceiverWindowFrame::PresentationReceiverWindowFrame( + Profile* profile) + : profile_(profile) {} +PresentationReceiverWindowFrame::~PresentationReceiverWindowFrame() = default; + +void PresentationReceiverWindowFrame::InitReceiverFrame( + std::unique_ptr<views::WidgetDelegateView> delegate, + const gfx::Rect& bounds) { + views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW); + params.bounds = bounds; + params.delegate = delegate.release(); + + Init(params); +} + +const ui::ThemeProvider* PresentationReceiverWindowFrame::GetThemeProvider() + const { + return &ThemeService::GetThemeProviderForProfile(profile_); +}
diff --git a/chrome/browser/ui/views/media_router/presentation_receiver_window_frame.h b/chrome/browser/ui/views/media_router/presentation_receiver_window_frame.h new file mode 100644 index 0000000..34453af6 --- /dev/null +++ b/chrome/browser/ui/views/media_router/presentation_receiver_window_frame.h
@@ -0,0 +1,47 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_MEDIA_ROUTER_PRESENTATION_RECEIVER_WINDOW_FRAME_H_ +#define CHROME_BROWSER_UI_VIEWS_MEDIA_ROUTER_PRESENTATION_RECEIVER_WINDOW_FRAME_H_ + +#include <memory> + +#include "base/macros.h" +#include "ui/views/widget/widget.h" + +namespace gfx { +class Rect; +} + +namespace ui { +class ThemeProvider; +} + +class Profile; + +namespace views { +class WidgetDelegateView; +} + +// This class implements the window portion of PresentationReceiverWindow. It +// is just a normal Widget that overrides GetThemeProvider to provide normal +// colors for the URL bar. +class PresentationReceiverWindowFrame final : public views::Widget { + public: + explicit PresentationReceiverWindowFrame(Profile* profile); + ~PresentationReceiverWindowFrame() final; + + void InitReceiverFrame(std::unique_ptr<views::WidgetDelegateView> delegate, + const gfx::Rect& bounds); + + private: + const ui::ThemeProvider* GetThemeProvider() const final; + + // The profile from which we get the theme. + Profile* const profile_; + + DISALLOW_COPY_AND_ASSIGN(PresentationReceiverWindowFrame); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_MEDIA_ROUTER_PRESENTATION_RECEIVER_WINDOW_FRAME_H_
diff --git a/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc b/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc new file mode 100644 index 0000000..e033a9a --- /dev/null +++ b/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc
@@ -0,0 +1,308 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/media_router/presentation_receiver_window_view.h" + +#include "base/logging.h" +#include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/content_settings/mixed_content_settings_tab_helper.h" +#include "chrome/browser/content_settings/tab_specific_content_settings.h" +#include "chrome/browser/infobars/infobar_service.h" +#include "chrome/browser/password_manager/chrome_password_manager_client.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ssl/security_state_tab_helper.h" +#include "chrome/browser/subresource_filter/chrome_subresource_filter_client.h" +#include "chrome/browser/translate/chrome_translate_client.h" +#include "chrome/browser/ui/autofill/chrome_autofill_client.h" +#include "chrome/browser/ui/blocked_content/framebust_block_tab_helper.h" +#include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h" +#include "chrome/browser/ui/media_router/presentation_receiver_window_delegate.h" +#include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h" +#include "chrome/browser/ui/search/search_tab_helper.h" +#include "chrome/browser/ui/tab_dialogs.h" +#include "chrome/browser/ui/views/accelerator_table.h" +#include "chrome/browser/ui/views/exclusive_access_bubble_views.h" +#include "chrome/browser/ui/views/media_router/presentation_receiver_window_frame.h" +#include "components/toolbar/toolbar_model_impl.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/content_constants.h" +#include "ui/base/accelerators/accelerator_manager.h" +#include "ui/display/screen.h" +#include "ui/gfx/geometry/point.h" +#include "ui/views/controls/webview/webview.h" +#include "ui/views/focus/focus_manager.h" +#include "ui/views/layout/box_layout.h" +#include "ui/views/widget/widget.h" + +using content::WebContents; + +PresentationReceiverWindowView::PresentationReceiverWindowView( + PresentationReceiverWindowFrame* frame, + PresentationReceiverWindowDelegate* delegate) + : frame_(frame), + delegate_(delegate), + toolbar_model_( + std::make_unique<ToolbarModelImpl>(this, + content::kMaxURLDisplayChars)), + command_updater_(this), + exclusive_access_manager_(this) { + DCHECK(frame); + DCHECK(delegate); +} + +PresentationReceiverWindowView::~PresentationReceiverWindowView() = default; + +void PresentationReceiverWindowView::Init() { + auto* const focus_manager = GetFocusManager(); + DCHECK(focus_manager); + + const auto accelerators = GetAcceleratorList(); + const auto fullscreen_accelerator = + std::find_if(accelerators.begin(), accelerators.end(), + [](const AcceleratorMapping& accelerator) { + return accelerator.command_id == IDC_FULLSCREEN; + }); + DCHECK(fullscreen_accelerator != accelerators.end()); + fullscreen_accelerator_ = ui::Accelerator(fullscreen_accelerator->keycode, + fullscreen_accelerator->modifiers); + focus_manager->RegisterAccelerator( + fullscreen_accelerator_, ui::AcceleratorManager::kNormalPriority, this); + + auto* const web_contents = GetWebContents(); + DCHECK(web_contents); + + SecurityStateTabHelper::CreateForWebContents(web_contents); + ChromeTranslateClient::CreateForWebContents(web_contents); + autofill::ChromeAutofillClient::CreateForWebContents(web_contents); + ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient( + web_contents, + autofill::ChromeAutofillClient::FromWebContents(web_contents)); + ManagePasswordsUIController::CreateForWebContents(web_contents); + SearchTabHelper::CreateForWebContents(web_contents); + TabDialogs::CreateForWebContents(web_contents); + FramebustBlockTabHelper::CreateForWebContents(web_contents); + ChromeSubresourceFilterClient::CreateForWebContents(web_contents); + InfoBarService::CreateForWebContents(web_contents); + MixedContentSettingsTabHelper::CreateForWebContents(web_contents); + PopupBlockerTabHelper::CreateForWebContents(web_contents); + TabSpecificContentSettings::CreateForWebContents(web_contents); + + auto* profile = + Profile::FromBrowserContext(web_contents->GetBrowserContext()); + auto* web_view = new views::WebView(profile); + web_view->SetWebContents(web_contents); + web_view->set_allow_accelerators(true); + location_bar_view_ = + new LocationBarView(nullptr, profile, &command_updater_, this, true); + + auto* box = new views::BoxLayout(views::BoxLayout::kVertical); + box->set_cross_axis_alignment(views::BoxLayout::CROSS_AXIS_ALIGNMENT_STRETCH); + SetLayoutManager(box); + AddChildView(location_bar_view_); + box->SetFlexForView(location_bar_view_, 0); + AddChildView(web_view); + box->SetFlexForView(web_view, 1); + + location_bar_view_->Init(); +} + +void PresentationReceiverWindowView::Close() { + frame_->Close(); +} + +bool PresentationReceiverWindowView::IsWindowActive() const { + return frame_->IsActive(); +} + +bool PresentationReceiverWindowView::IsWindowFullscreen() const { + return frame_->IsFullscreen(); +} + +gfx::Rect PresentationReceiverWindowView::GetWindowBounds() const { + return frame_->GetWindowBoundsInScreen(); +} + +void PresentationReceiverWindowView::ShowInactiveFullscreen() { + frame_->ShowInactive(); + exclusive_access_manager_.fullscreen_controller() + ->ToggleBrowserFullscreenMode(); +} + +void PresentationReceiverWindowView::UpdateWindowTitle() { + frame_->UpdateWindowTitle(); +} + +void PresentationReceiverWindowView::UpdateLocationBar() { + DCHECK(location_bar_view_); + location_bar_view_->Update(nullptr); +} + +WebContents* PresentationReceiverWindowView::GetWebContents() { + return delegate_->web_contents(); +} + +ToolbarModel* PresentationReceiverWindowView::GetToolbarModel() { + return toolbar_model_.get(); +} + +const ToolbarModel* PresentationReceiverWindowView::GetToolbarModel() const { + return toolbar_model_.get(); +} + +ContentSettingBubbleModelDelegate* +PresentationReceiverWindowView::GetContentSettingBubbleModelDelegate() { + NOTREACHED(); + return nullptr; +} + +void PresentationReceiverWindowView::ExecuteCommandWithDisposition( + int id, + WindowOpenDisposition disposition) { + NOTREACHED(); +} + +WebContents* PresentationReceiverWindowView::GetActiveWebContents() const { + return delegate_->web_contents(); +} + +bool PresentationReceiverWindowView::CanResize() const { + return true; +} + +bool PresentationReceiverWindowView::CanMaximize() const { + return true; +} + +bool PresentationReceiverWindowView::CanMinimize() const { + return true; +} + +void PresentationReceiverWindowView::DeleteDelegate() { + auto* const delegate = delegate_; + delete this; + delegate->WindowClosed(); +} + +base::string16 PresentationReceiverWindowView::GetWindowTitle() const { + return delegate_->web_contents()->GetTitle(); +} + +bool PresentationReceiverWindowView::AcceleratorPressed( + const ui::Accelerator& accelerator) { + exclusive_access_manager_.fullscreen_controller() + ->ToggleBrowserFullscreenMode(); + return true; +} + +Profile* PresentationReceiverWindowView::GetProfile() { + return Profile::FromBrowserContext( + delegate_->web_contents()->GetBrowserContext()); +} + +bool PresentationReceiverWindowView::IsFullscreen() const { + return frame_->IsFullscreen(); +} + +void PresentationReceiverWindowView::EnterFullscreen( + const GURL& url, + ExclusiveAccessBubbleType bubble_type) { + location_bar_view_->SetVisible(false); + frame_->SetFullscreen(true); + UpdateExclusiveAccessExitBubbleContent(url, bubble_type, + ExclusiveAccessBubbleHideCallback()); +} + +void PresentationReceiverWindowView::ExitFullscreen() { + exclusive_access_bubble_.reset(); + location_bar_view_->SetVisible(true); + frame_->SetFullscreen(false); +} + +void PresentationReceiverWindowView::UpdateExclusiveAccessExitBubbleContent( + const GURL& url, + ExclusiveAccessBubbleType bubble_type, + ExclusiveAccessBubbleHideCallback bubble_first_hide_callback) { + if (bubble_type == EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE) { + // |exclusive_access_bubble_.reset()| will trigger callback for current + // bubble with |ExclusiveAccessBubbleHideReason::kInterrupted| if available. + exclusive_access_bubble_.reset(); + if (bubble_first_hide_callback) { + std::move(bubble_first_hide_callback) + .Run(ExclusiveAccessBubbleHideReason::kNotShown); + } + return; + } + + if (exclusive_access_bubble_) { + exclusive_access_bubble_->UpdateContent( + url, bubble_type, std::move(bubble_first_hide_callback)); + return; + } + + exclusive_access_bubble_ = std::make_unique<ExclusiveAccessBubbleViews>( + this, url, bubble_type, std::move(bubble_first_hide_callback)); +} + +void PresentationReceiverWindowView::OnExclusiveAccessUserInput() {} + +content::WebContents* PresentationReceiverWindowView::GetActiveWebContents() { + return delegate_->web_contents(); +} + +void PresentationReceiverWindowView::UnhideDownloadShelf() {} + +void PresentationReceiverWindowView::HideDownloadShelf() {} + +ExclusiveAccessManager* +PresentationReceiverWindowView::GetExclusiveAccessManager() { + return &exclusive_access_manager_; +} + +views::Widget* PresentationReceiverWindowView::GetBubbleAssociatedWidget() { + return frame_; +} + +ui::AcceleratorProvider* +PresentationReceiverWindowView::GetAcceleratorProvider() { + return this; +} + +gfx::NativeView PresentationReceiverWindowView::GetBubbleParentView() const { + return frame_->GetNativeView(); +} + +gfx::Point PresentationReceiverWindowView::GetCursorPointInParent() const { + gfx::Point cursor_pos = display::Screen::GetScreen()->GetCursorScreenPoint(); + views::View::ConvertPointFromScreen(GetWidget()->GetRootView(), &cursor_pos); + return cursor_pos; +} + +gfx::Rect PresentationReceiverWindowView::GetClientAreaBoundsInScreen() const { + return GetWidget()->GetClientAreaBoundsInScreen(); +} + +bool PresentationReceiverWindowView::IsImmersiveModeEnabled() const { + return false; +} + +gfx::Rect PresentationReceiverWindowView::GetTopContainerBoundsInScreen() { + return GetBoundsInScreen(); +} + +void PresentationReceiverWindowView::DestroyAnyExclusiveAccessBubble() { + exclusive_access_bubble_.reset(); +} + +bool PresentationReceiverWindowView::CanTriggerOnMouse() const { + return true; +} + +bool PresentationReceiverWindowView::GetAcceleratorForCommandId( + int command_id, + ui::Accelerator* accelerator) const { + if (command_id != IDC_FULLSCREEN) + return false; + *accelerator = fullscreen_accelerator_; + return true; +}
diff --git a/chrome/browser/ui/views/media_router/presentation_receiver_window_view.h b/chrome/browser/ui/views/media_router/presentation_receiver_window_view.h new file mode 100644 index 0000000..b9d80d2 --- /dev/null +++ b/chrome/browser/ui/views/media_router/presentation_receiver_window_view.h
@@ -0,0 +1,124 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_MEDIA_ROUTER_PRESENTATION_RECEIVER_WINDOW_VIEW_H_ +#define CHROME_BROWSER_UI_VIEWS_MEDIA_ROUTER_PRESENTATION_RECEIVER_WINDOW_VIEW_H_ + +#include <memory> + +#include "base/macros.h" +#include "base/strings/string16.h" +#include "chrome/browser/command_updater_delegate.h" +#include "chrome/browser/command_updater_impl.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" +#include "chrome/browser/ui/media_router/presentation_receiver_window.h" +#include "chrome/browser/ui/toolbar/chrome_toolbar_model_delegate.h" +#include "chrome/browser/ui/views/exclusive_access_bubble_views_context.h" +#include "chrome/browser/ui/views/location_bar/location_bar_view.h" +#include "ui/views/widget/widget_delegate.h" + +class ExclusiveAccessBubbleViews; +class PresentationReceiverWindowDelegate; +class PresentationReceiverWindowFrame; +class ToolbarModelImpl; + +// This class implements the View portion of PresentationReceiverWindow. It +// contains a WebView for displaying the receiver page and a LocationBarView for +// displaying the URL. +class PresentationReceiverWindowView final + : public PresentationReceiverWindow, + public views::WidgetDelegateView, + public LocationBarView::Delegate, + public CommandUpdaterDelegate, + public ChromeToolbarModelDelegate, + public ExclusiveAccessContext, + public ExclusiveAccessBubbleViewsContext, + public ui::AcceleratorProvider { + public: + PresentationReceiverWindowView(PresentationReceiverWindowFrame* frame, + PresentationReceiverWindowDelegate* delegate); + ~PresentationReceiverWindowView() final; + + void Init(); + + private: + // PresentationReceiverWindow overrides. + void Close() final; + bool IsWindowActive() const final; + bool IsWindowFullscreen() const final; + gfx::Rect GetWindowBounds() const final; + void ShowInactiveFullscreen() final; + void UpdateWindowTitle() final; + void UpdateLocationBar() final; + + // LocationBarView::Delegate overrides. + content::WebContents* GetWebContents() final; + ToolbarModel* GetToolbarModel() final; + const ToolbarModel* GetToolbarModel() const final; + ContentSettingBubbleModelDelegate* GetContentSettingBubbleModelDelegate() + final; + + // CommandUpdaterDelegate overrides. + void ExecuteCommandWithDisposition(int id, + WindowOpenDisposition disposition) final; + + // ChromeToolbarModelDelegate overrides. + content::WebContents* GetActiveWebContents() const final; + + // views::WidgetDelegateView overrides. + bool CanResize() const final; + bool CanMaximize() const final; + bool CanMinimize() const final; + void DeleteDelegate() final; + base::string16 GetWindowTitle() const final; + + // ui::AcceleratorTarget overrides. + bool AcceleratorPressed(const ui::Accelerator& accelerator) final; + + // ExclusiveAccessContext overrides. + Profile* GetProfile() final; + bool IsFullscreen() const final; + void EnterFullscreen(const GURL& url, + ExclusiveAccessBubbleType bubble_type) final; + void ExitFullscreen() final; + void UpdateExclusiveAccessExitBubbleContent( + const GURL& url, + ExclusiveAccessBubbleType bubble_type, + ExclusiveAccessBubbleHideCallback bubble_first_hide_callback) final; + void OnExclusiveAccessUserInput() final; + content::WebContents* GetActiveWebContents() final; + void UnhideDownloadShelf() final; + void HideDownloadShelf() final; + + // ExclusiveAccessBubbleViewsContext overrides. + ExclusiveAccessManager* GetExclusiveAccessManager() final; + views::Widget* GetBubbleAssociatedWidget() final; + ui::AcceleratorProvider* GetAcceleratorProvider() final; + gfx::NativeView GetBubbleParentView() const final; + gfx::Point GetCursorPointInParent() const final; + gfx::Rect GetClientAreaBoundsInScreen() const final; + bool IsImmersiveModeEnabled() const final; + gfx::Rect GetTopContainerBoundsInScreen() final; + void DestroyAnyExclusiveAccessBubble() final; + bool CanTriggerOnMouse() const final; + + // ui::AcceleratorProvider overrides. + bool GetAcceleratorForCommandId(int command_id, + ui::Accelerator* accelerator) const final; + + PresentationReceiverWindowFrame* const frame_; + PresentationReceiverWindowDelegate* const delegate_; + base::string16 title_; + const std::unique_ptr<ToolbarModelImpl> toolbar_model_; + CommandUpdaterImpl command_updater_; + LocationBarView* location_bar_view_ = nullptr; + ExclusiveAccessManager exclusive_access_manager_; + ui::Accelerator fullscreen_accelerator_; + std::unique_ptr<ExclusiveAccessBubbleViews> exclusive_access_bubble_; + + DISALLOW_COPY_AND_ASSIGN(PresentationReceiverWindowView); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_MEDIA_ROUTER_PRESENTATION_RECEIVER_WINDOW_VIEW_H_
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc index 6e5dff4..24f1056 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_browsertest.cc
@@ -462,6 +462,16 @@ gfx::NO_ELIDE); } +IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, FragmentUnescapedForDisplay) { + OmniboxView* view = nullptr; + ASSERT_NO_FATAL_FAILURE(GetOmniboxViewForBrowser(browser(), &view)); + ui_test_utils::NavigateToURL(browser(), + GURL("https://www.google.com/#%E2%98%83")); + + EXPECT_EQ(view->GetText(), + base::UTF8ToUTF16("https://www.google.com/#\u2603")); +} + IN_PROC_BROWSER_TEST_F(OmniboxViewViewsTest, FriendlyAccessibleLabel) { OmniboxView* omnibox_view = nullptr; ASSERT_NO_FATAL_FAILURE(GetOmniboxViewForBrowser(browser(), &omnibox_view));
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc index b349dd3a..8aa4b3e 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h" #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h" #include "chrome/browser/command_updater.h" +#include "chrome/browser/command_updater_impl.h" #include "chrome/browser/search_engines/template_url_service_factory_test_util.h" #include "chrome/browser/ui/omnibox/chrome_omnibox_client.h" #include "chrome/browser/ui/omnibox/chrome_omnibox_edit_controller.h" @@ -208,7 +209,7 @@ content::TestBrowserThreadBundle thread_bundle_; TestingProfile profile_; TemplateURLServiceFactoryTestUtil util_; - CommandUpdater command_updater_; + CommandUpdaterImpl command_updater_; TestToolbarModel toolbar_model_; TestingOmniboxEditController omnibox_edit_controller_; std::unique_ptr<TestingOmniboxView> omnibox_view_;
diff --git a/chrome/browser/ui/views/page_info/chosen_object_view.cc b/chrome/browser/ui/views/page_info/chosen_object_view.cc index 7915b527..4aff5eb 100644 --- a/chrome/browser/ui/views/page_info/chosen_object_view.cc +++ b/chrome/browser/ui/views/page_info/chosen_object_view.cc
@@ -31,7 +31,8 @@ constexpr float kFixed = 0.f; constexpr float kStretchy = 1.f; - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); const int column_set_id = 0; views::ColumnSet* column_set = layout->AddColumnSet(column_set_id); column_set->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER,
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc index f1b91158..c541da5 100644 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
@@ -122,7 +122,8 @@ (*link)->SetTooltipText(tooltip_text); views::View* new_view = new views::View(); - GridLayout* layout = GridLayout::CreateAndInstall(new_view); + GridLayout* layout = + new_view->SetLayoutManager(std::make_unique<views::GridLayout>(new_view)); ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); const int side_margin = provider->GetInsetsMetric(views::INSETS_DIALOG_SUBSECTION).left(); @@ -312,7 +313,8 @@ password_reuse_button_container_(nullptr), change_password_button_(nullptr), whitelist_password_reuse_button_(nullptr) { - GridLayout* layout = GridLayout::CreateAndInstall(this); + GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); const int label_column_status = 1; AddColumnWithSideMargin(layout, side_margin, label_column_status); @@ -573,7 +575,8 @@ UseHarmonyStyle() ? hover_list_spacing : margins().bottom(); set_margins(gfx::Insets(margins().top(), 0, bottom_margin, 0)); - GridLayout* layout = GridLayout::CreateAndInstall(this); + GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); constexpr int kColumnId = 0; views::ColumnSet* column_set = layout->AddColumnSet(kColumnId); column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, @@ -756,7 +759,8 @@ if (permissions_view_->has_children()) return; - GridLayout* layout = GridLayout::CreateAndInstall(permissions_view_); + GridLayout* layout = permissions_view_->SetLayoutManager( + std::make_unique<views::GridLayout>(permissions_view_)); ChromeLayoutProvider* layout_provider = ChromeLayoutProvider::Get(); const int list_item_padding =
diff --git a/chrome/browser/ui/views/passwords/credentials_selection_view.cc b/chrome/browser/ui/views/passwords/credentials_selection_view.cc index 8b43b95..d86e24d 100644 --- a/chrome/browser/ui/views/passwords/credentials_selection_view.cc +++ b/chrome/browser/ui/views/passwords/credentials_selection_view.cc
@@ -38,7 +38,8 @@ DCHECK(!password_forms_->empty()); // Layout. - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); SetLayoutManager(layout); // ColumnSet.
diff --git a/chrome/browser/ui/views/passwords/manage_password_items_view.cc b/chrome/browser/ui/views/passwords/manage_password_items_view.cc index aab01ea..800181f3 100644 --- a/chrome/browser/ui/views/passwords/manage_password_items_view.cc +++ b/chrome/browser/ui/views/passwords/manage_password_items_view.cc
@@ -250,7 +250,8 @@ RemoveAllChildViews(true); - views::GridLayout* grid_layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* grid_layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); const int vertical_padding = ChromeLayoutProvider::Get()->GetDistanceMetric( DISTANCE_CONTROL_LIST_VERTICAL);
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 106a0c7..72e9b466 100644 --- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc +++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
@@ -558,7 +558,8 @@ void ManagePasswordsBubbleView::PendingView::CreateAndSetLayout( bool show_password_label) { - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); layout->set_minimum_size(gfx::Size(kDesiredBubbleWidth, 0)); views::View* password_field = @@ -663,7 +664,8 @@ ManagePasswordsBubbleView::SaveConfirmationView::SaveConfirmationView( ManagePasswordsBubbleView* parent) : parent_(parent) { - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); layout->set_minimum_size(gfx::Size(kDesiredBubbleWidth, 0)); views::StyledLabel* confirmation = @@ -733,7 +735,8 @@ ManagePasswordsBubbleView::SignInPromoView::SignInPromoView( ManagePasswordsBubbleView* parent) : parent_(parent) { - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); layout->set_minimum_size(gfx::Size(kDesiredBubbleWidth, 0)); signin_button_ = views::MdTextButton::CreateSecondaryUiBlueButton( @@ -800,7 +803,8 @@ ManagePasswordsBubbleView* parent) : parent_(parent), selection_view_(nullptr) { ChromeLayoutProvider* layout_provider = ChromeLayoutProvider::Get(); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); layout->set_minimum_size(gfx::Size(kDesiredBubbleWidth, 0)); // Credential row.
diff --git a/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc b/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc index b25ad0a..3228843 100644 --- a/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc +++ b/chrome/browser/ui/views/payments/credit_card_editor_view_controller.cc
@@ -293,7 +293,7 @@ } else { // Two comboboxes, one for month and the other for year. views::GridLayout* combobox_layout = - views::GridLayout::CreateAndInstall(view.get()); + view->SetLayoutManager(std::make_unique<views::GridLayout>(view.get())); views::ColumnSet* columns = combobox_layout->AddColumnSet(0); columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, 1, views::GridLayout::USE_PREF, 0, 0);
diff --git a/chrome/browser/ui/views/payments/cvc_unmask_view_controller.cc b/chrome/browser/ui/views/payments/cvc_unmask_view_controller.cc index 81b0479..148f3d0 100644 --- a/chrome/browser/ui/views/payments/cvc_unmask_view_controller.cc +++ b/chrome/browser/ui/views/payments/cvc_unmask_view_controller.cc
@@ -148,7 +148,8 @@ } void CvcUnmaskViewController::FillContentView(views::View* content_view) { - views::GridLayout* layout = views::GridLayout::CreateAndInstall(content_view); + views::GridLayout* layout = content_view->SetLayoutManager( + std::make_unique<views::GridLayout>(content_view)); content_view->SetBorder(views::CreateEmptyBorder( kPaymentRequestRowVerticalInsets, kPaymentRequestRowHorizontalInsets, kPaymentRequestRowVerticalInsets, kPaymentRequestRowHorizontalInsets));
diff --git a/chrome/browser/ui/views/payments/editor_view_controller.cc b/chrome/browser/ui/views/payments/editor_view_controller.cc index 276f154..344c04d 100644 --- a/chrome/browser/ui/views/payments/editor_view_controller.cc +++ b/chrome/browser/ui/views/payments/editor_view_controller.cc
@@ -251,8 +251,8 @@ constexpr int kShortFieldMinimumWidth = 176; constexpr int kLongFieldMinimumWidth = 272; - views::GridLayout* editor_layout = - views::GridLayout::CreateAndInstall(editor_view.get()); + views::GridLayout* editor_layout = editor_view->SetLayoutManager( + std::make_unique<views::GridLayout>(editor_view.get())); // Column set for short fields. views::ColumnSet* columns_short = editor_layout->AddColumnSet(0); columns_short->AddColumn(views::GridLayout::LEADING,
diff --git a/chrome/browser/ui/views/payments/order_summary_view_controller.cc b/chrome/browser/ui/views/payments/order_summary_view_controller.cc index a0d1db93..87cacaa 100644 --- a/chrome/browser/ui/views/payments/order_summary_view_controller.cc +++ b/chrome/browser/ui/views/payments/order_summary_view_controller.cc
@@ -57,7 +57,8 @@ ui::NativeTheme::kColorId_SeparatorColor), row_insets)); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(row.get()); + views::GridLayout* layout = + row->SetLayoutManager(std::make_unique<views::GridLayout>(row.get())); views::ColumnSet* columns = layout->AddColumnSet(0); // The first column has resize_percent = 1 so that it stretches all the way @@ -94,8 +95,8 @@ amount_text->SetAllowCharacterBreak(true); std::unique_ptr<views::View> amount_wrapper = base::MakeUnique<views::View>(); - views::GridLayout* wrapper_layout = - views::GridLayout::CreateAndInstall(amount_wrapper.get()); + views::GridLayout* wrapper_layout = amount_wrapper->SetLayoutManager( + std::make_unique<views::GridLayout>(amount_wrapper.get())); views::ColumnSet* wrapper_columns = wrapper_layout->AddColumnSet(0); wrapper_columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, 0,
diff --git a/chrome/browser/ui/views/payments/payment_request_dialog_view.cc b/chrome/browser/ui/views/payments/payment_request_dialog_view.cc index db07676..4746831 100644 --- a/chrome/browser/ui/views/payments/payment_request_dialog_view.cc +++ b/chrome/browser/ui/views/payments/payment_request_dialog_view.cc
@@ -371,8 +371,8 @@ // would be under it. throbber_overlay_.SetBackground(views::CreateSolidBackground(SK_ColorWHITE)); - views::GridLayout* layout = - views::GridLayout::CreateAndInstall(&throbber_overlay_); + views::GridLayout* layout = throbber_overlay_.SetLayoutManager( + std::make_unique<views::GridLayout>(&throbber_overlay_)); views::ColumnSet* throbber_columns = layout->AddColumnSet(0); throbber_columns->AddPaddingColumn(0.5, 0); throbber_columns->AddColumn(views::GridLayout::Alignment::CENTER,
diff --git a/chrome/browser/ui/views/payments/payment_request_item_list.cc b/chrome/browser/ui/views/payments/payment_request_item_list.cc index 3420c0e6..e7c96f9 100644 --- a/chrome/browser/ui/views/payments/payment_request_item_list.cc +++ b/chrome/browser/ui/views/payments/payment_request_item_list.cc
@@ -63,7 +63,8 @@ std::unique_ptr<views::View> content = CreateContentView(&accessible_item_description_); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); // Add a column for the item's content view. views::ColumnSet* columns = layout->AddColumnSet(0);
diff --git a/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc b/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc index cf1a391e..a609b34 100644 --- a/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc +++ b/chrome/browser/ui/views/payments/payment_request_sheet_controller.cc
@@ -218,7 +218,8 @@ // layer) won't do proper clipping. view->SetPaintToLayer(); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(view.get()); + views::GridLayout* layout = + view->SetLayoutManager(std::make_unique<views::GridLayout>(view.get())); // Note: each view is responsible for its own padding (insets). views::ColumnSet* columns = layout->AddColumnSet(0); @@ -236,7 +237,8 @@ // otherwise it'll be sized to the ScrollView's viewport height, preventing // the scroll bar from ever being shown. pane_ = new views::View; - views::GridLayout* pane_layout = views::GridLayout::CreateAndInstall(pane_); + views::GridLayout* pane_layout = + pane_->SetLayoutManager(std::make_unique<views::GridLayout>(pane_)); views::ColumnSet* pane_columns = pane_layout->AddColumnSet(0); pane_columns->AddColumn(views::GridLayout::Alignment::FILL, views::GridLayout::Alignment::LEADING, 0, @@ -343,8 +345,8 @@ container->SetBorder( views::CreateEmptyBorder(kInset, kInset, kInset, kInset)); - views::GridLayout* layout = - views::GridLayout::CreateAndInstall(container.get()); + views::GridLayout* layout = container->SetLayoutManager( + std::make_unique<views::GridLayout>(container.get())); views::ColumnSet* columns = layout->AddColumnSet(0); columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
diff --git a/chrome/browser/ui/views/payments/payment_request_views_util.cc b/chrome/browser/ui/views/payments/payment_request_views_util.cc index e87a80b..c78516f7 100644 --- a/chrome/browser/ui/views/payments/payment_request_views_util.cc +++ b/chrome/browser/ui/views/payments/payment_request_views_util.cc
@@ -185,8 +185,8 @@ const base::string16& title, views::ButtonListener* listener) { std::unique_ptr<views::View> container = base::MakeUnique<views::View>(); - views::GridLayout* layout = - views::GridLayout::CreateAndInstall(container.get()); + views::GridLayout* layout = container->SetLayoutManager( + std::make_unique<views::GridLayout>(container.get())); constexpr int kHeaderTopVerticalInset = 14; constexpr int kHeaderBottomVerticalInset = 8;
diff --git a/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc b/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc index fee876f..89d198c 100644 --- a/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc +++ b/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc
@@ -151,7 +151,8 @@ kPaymentRequestRowVerticalInsets, trailing_inset); std::unique_ptr<PaymentRequestRowView> row = base::MakeUnique<PaymentRequestRowView>(listener, clickable, row_insets); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(row.get()); + views::GridLayout* layout = + row->SetLayoutManager(std::make_unique<views::GridLayout>(row.get())); views::ColumnSet* columns = layout->AddColumnSet(0); // A column for the section name. @@ -211,8 +212,8 @@ bool bold) { std::unique_ptr<views::View> item_amount_line = base::MakeUnique<views::View>(); - views::GridLayout* item_amount_layout = - views::GridLayout::CreateAndInstall(item_amount_line.get()); + views::GridLayout* item_amount_layout = item_amount_line->SetLayoutManager( + std::make_unique<views::GridLayout>(item_amount_line.get())); views::ColumnSet* item_amount_columns = item_amount_layout->AddColumnSet(0); item_amount_columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING, 0, @@ -412,7 +413,8 @@ } void PaymentSheetViewController::FillContentView(views::View* content_view) { - views::GridLayout* layout = views::GridLayout::CreateAndInstall(content_view); + views::GridLayout* layout = content_view->SetLayoutManager( + std::make_unique<views::GridLayout>(content_view)); views::ColumnSet* columns = layout->AddColumnSet(0); columns->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER, 1, views::GridLayout::USE_PREF, 0, 0); @@ -561,8 +563,8 @@ std::unique_ptr<PaymentRequestRowView> PaymentSheetViewController::CreatePaymentSheetSummaryRow() { std::unique_ptr<views::View> inline_summary = base::MakeUnique<views::View>(); - views::GridLayout* layout = - views::GridLayout::CreateAndInstall(inline_summary.get()); + views::GridLayout* layout = inline_summary->SetLayoutManager( + std::make_unique<views::GridLayout>(inline_summary.get())); views::ColumnSet* columns = layout->AddColumnSet(0); columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING, 1, views::GridLayout::USE_PREF, 0, 0); @@ -727,8 +729,8 @@ if (selected_instrument) { std::unique_ptr<views::View> content_view = base::MakeUnique<views::View>(); - views::GridLayout* layout = - views::GridLayout::CreateAndInstall(content_view.get()); + views::GridLayout* layout = content_view->SetLayoutManager( + std::make_unique<views::GridLayout>(content_view.get())); views::ColumnSet* columns = layout->AddColumnSet(0); columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER, 1, views::GridLayout::USE_PREF, 0, 0);
diff --git a/chrome/browser/ui/views/profiles/forced_reauthentication_dialog_view.cc b/chrome/browser/ui/views/profiles/forced_reauthentication_dialog_view.cc index b0a76c74..4fdb0db 100644 --- a/chrome/browser/ui/views/profiles/forced_reauthentication_dialog_view.cc +++ b/chrome/browser/ui/views/profiles/forced_reauthentication_dialog_view.cc
@@ -209,7 +209,8 @@ provider->GetDialogInsetsForContentType(views::TEXT, views::TEXT); SetBorder(views::CreateEmptyBorder(dialog_insets.top(), 0, dialog_insets.bottom(), 0)); - views::GridLayout* dialog_layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* dialog_layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); SetLayoutManager(dialog_layout); // Use a column set with no padding.
diff --git a/chrome/browser/ui/views/profiles/profile_chooser_view.cc b/chrome/browser/ui/views/profiles/profile_chooser_view.cc index f2c1d96b..b4d83c1 100644 --- a/chrome/browser/ui/views/profiles/profile_chooser_view.cc +++ b/chrome/browser/ui/views/profiles/profile_chooser_view.cc
@@ -118,7 +118,8 @@ // Creates a GridLayout with a single column. This ensures that all the child // views added get auto-expanded to fill the full width of the bubble. views::GridLayout* CreateSingleColumnLayout(views::View* view, int width) { - views::GridLayout* layout = views::GridLayout::CreateAndInstall(view); + views::GridLayout* layout = + view->SetLayoutManager(std::make_unique<views::GridLayout>(view)); views::ColumnSet* columns = layout->AddColumnSet(0); columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0, @@ -202,8 +203,8 @@ TitleCard* title_card, int width) { views::View* titled_view = new views::View(); - views::GridLayout* layout = - views::GridLayout::CreateAndInstall(titled_view); + views::GridLayout* layout = titled_view->SetLayoutManager( + std::make_unique<views::GridLayout>(titled_view)); ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); const gfx::Insets dialog_insets =
diff --git a/chrome/browser/ui/views/proximity_auth/proximity_auth_error_bubble_view.cc b/chrome/browser/ui/views/proximity_auth/proximity_auth_error_bubble_view.cc index 5fc2d8d..3cf136a 100644 --- a/chrome/browser/ui/views/proximity_auth/proximity_auth_error_bubble_view.cc +++ b/chrome/browser/ui/views/proximity_auth/proximity_auth_error_bubble_view.cc
@@ -94,7 +94,8 @@ // ---------------------------- // | icon | padding | message | // ---------------------------- - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); views::ColumnSet* columns = layout->AddColumnSet(0); columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING, 0, views::GridLayout::USE_PREF, 0, 0);
diff --git a/chrome/browser/ui/views/sad_tab_view.cc b/chrome/browser/ui/views/sad_tab_view.cc index 2bda4f60..84ce665 100644 --- a/chrome/browser/ui/views/sad_tab_view.cc +++ b/chrome/browser/ui/views/sad_tab_view.cc
@@ -52,7 +52,8 @@ SetBackground(views::CreateThemedSolidBackground( this, ui::NativeTheme::kColorId_DialogBackground)); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); const int column_set_id = 0; views::ColumnSet* columns = layout->AddColumnSet(column_set_id);
diff --git a/chrome/browser/ui/views/safe_browsing/password_reuse_modal_warning_dialog.cc b/chrome/browser/ui/views/safe_browsing/password_reuse_modal_warning_dialog.cc index f786b757..cecc1812 100644 --- a/chrome/browser/ui/views/safe_browsing/password_reuse_modal_warning_dialog.cc +++ b/chrome/browser/ui/views/safe_browsing/password_reuse_modal_warning_dialog.cc
@@ -57,7 +57,7 @@ const ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); set_margins( provider->GetDialogInsetsForContentType(views::TEXT, views::TEXT)); - SetLayoutManager(new views::FillLayout()); + SetLayoutManager(std::make_unique<views::FillLayout>()); views::Label* message_body_label = new views::Label( l10n_util::GetStringUTF16(IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS));
diff --git a/chrome/browser/ui/views/session_crashed_bubble_view.cc b/chrome/browser/ui/views/session_crashed_bubble_view.cc index 7385bda1..6077131b9 100644 --- a/chrome/browser/ui/views/session_crashed_bubble_view.cc +++ b/chrome/browser/ui/views/session_crashed_bubble_view.cc
@@ -193,7 +193,7 @@ } void SessionCrashedBubbleView::Init() { - SetLayoutManager(new views::FillLayout()); + SetLayoutManager(std::make_unique<views::FillLayout>()); // Description text label. views::Label* text_label = new views::Label( @@ -242,7 +242,8 @@ // Create a view to hold the checkbox and the text. views::View* uma_view = new views::View(); - GridLayout* uma_layout = GridLayout::CreateAndInstall(uma_view); + GridLayout* uma_layout = + uma_view->SetLayoutManager(std::make_unique<views::GridLayout>(uma_view)); uma_view->SetLayoutManager(uma_layout); const int kReportColumnSetId = 0;
diff --git a/chrome/browser/ui/views/settings_reset_prompt_dialog.cc b/chrome/browser/ui/views/settings_reset_prompt_dialog.cc index bd7918b5..e2a4b94 100644 --- a/chrome/browser/ui/views/settings_reset_prompt_dialog.cc +++ b/chrome/browser/ui/views/settings_reset_prompt_dialog.cc
@@ -39,7 +39,7 @@ set_margins(ChromeLayoutProvider::Get()->GetDialogInsetsForContentType( views::TEXT, views::TEXT)); - SetLayoutManager(new views::FillLayout()); + SetLayoutManager(std::make_unique<views::FillLayout>()); views::StyledLabel* dialog_label = new views::StyledLabel(controller_->GetMainText(), /*listener=*/nullptr);
diff --git a/chrome/browser/ui/views/subtle_notification_view.cc b/chrome/browser/ui/views/subtle_notification_view.cc index 95e3306..1097d8c9 100644 --- a/chrome/browser/ui/views/subtle_notification_view.cc +++ b/chrome/browser/ui/views/subtle_notification_view.cc
@@ -78,9 +78,8 @@ SkColor background_color) : foreground_color_(foreground_color), background_color_(background_color) { // The |between_child_spacing| is the horizontal margin of the key name. - views::BoxLayout* layout = new views::BoxLayout( - views::BoxLayout::kHorizontal, gfx::Insets(), kKeyNameMarginHorizPx); - SetLayoutManager(layout); + SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::kHorizontal, gfx::Insets(), kKeyNameMarginHorizPx)); SetText(text); } @@ -125,11 +124,11 @@ } views::View* key = new views::View; - views::BoxLayout* key_name_layout = new views::BoxLayout( + auto key_name_layout = std::make_unique<views::BoxLayout>( views::BoxLayout::kHorizontal, gfx::Insets(0, kKeyNamePaddingPx), 0); key_name_layout->set_minimum_cross_axis_size( label->GetPreferredSize().height() + kKeyNamePaddingPx * 2); - key->SetLayoutManager(key_name_layout); + key->SetLayoutManager(std::move(key_name_layout)); key->AddChildView(label); // The key name has a border around it. std::unique_ptr<views::Border> border(views::CreateRoundedRectBorder( @@ -164,10 +163,9 @@ AddChildView(instruction_view_); AddChildView(link_); - views::BoxLayout* layout = new views::BoxLayout( + SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::kHorizontal, - gfx::Insets(outer_padding_vert, outer_padding_horiz), kMiddlePaddingPx); - SetLayoutManager(layout); + gfx::Insets(outer_padding_vert, outer_padding_horiz), kMiddlePaddingPx)); } SubtleNotificationView::~SubtleNotificationView() {}
diff --git a/chrome/browser/ui/views/sync/one_click_signin_dialog_view.cc b/chrome/browser/ui/views/sync/one_click_signin_dialog_view.cc index d03fceba..6db4e6c 100644 --- a/chrome/browser/ui/views/sync/one_click_signin_dialog_view.cc +++ b/chrome/browser/ui/views/sync/one_click_signin_dialog_view.cc
@@ -88,7 +88,8 @@ } void OneClickSigninDialogView::Init() { - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); // Column set for descriptive text and link. views::ColumnSet* cs = layout->AddColumnSet(0);
diff --git a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc index c66055c..cefffd1 100644 --- a/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc +++ b/chrome/browser/ui/views/sync/profile_signin_confirmation_dialog_views.cc
@@ -207,11 +207,12 @@ // insets. SetBorder(views::CreateEmptyBorder(content_insets.top(), 0, content_insets.bottom(), 0)); - views::GridLayout* dialog_layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* dialog_layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); // Use GridLayout inside the prompt bar because StyledLabel requires it. - views::GridLayout* prompt_layout = - views::GridLayout::CreateAndInstall(prompt_bar); + views::GridLayout* prompt_layout = prompt_bar->SetLayoutManager( + std::make_unique<views::GridLayout>(prompt_bar)); prompt_bar->SetBorder( views::CreateEmptyBorder(ChromeLayoutProvider::Get()->GetInsetsMetric( views::INSETS_DIALOG_SUBSECTION)));
diff --git a/chrome/browser/ui/views/task_manager_view.cc b/chrome/browser/ui/views/task_manager_view.cc index 6769e8dd..31c7cd8 100644 --- a/chrome/browser/ui/views/task_manager_view.cc +++ b/chrome/browser/ui/views/task_manager_view.cc
@@ -334,7 +334,7 @@ tab_table_parent_ = tab_table_->CreateParentIfNecessary(); AddChildView(tab_table_parent_); - SetLayoutManager(new views::FillLayout()); + SetLayoutManager(std::make_unique<views::FillLayout>()); const ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); const gfx::Insets dialog_insets =
diff --git a/chrome/browser/ui/views/toolbar/home_button.cc b/chrome/browser/ui/views/toolbar/home_button.cc index 4889a64..049a085 100644 --- a/chrome/browser/ui/views/toolbar/home_button.cc +++ b/chrome/browser/ui/views/toolbar/home_button.cc
@@ -102,7 +102,7 @@ } void HomePageUndoBubble::Init() { - SetLayoutManager(new views::FillLayout()); + SetLayoutManager(std::make_unique<views::FillLayout>()); base::string16 undo_string = l10n_util::GetStringUTF16(IDS_ONE_CLICK_BUBBLE_UNDO);
diff --git a/chrome/browser/ui/views/toolbar/toolbar_actions_bar_bubble_views.cc b/chrome/browser/ui/views/toolbar/toolbar_actions_bar_bubble_views.cc index 93c7a752..3b6e2b9 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_actions_bar_bubble_views.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_actions_bar_bubble_views.cc
@@ -78,10 +78,10 @@ if (icon && label) { views::View* parent = new views::View(); - parent->SetLayoutManager( - new views::BoxLayout(views::BoxLayout::kHorizontal, gfx::Insets(), - ChromeLayoutProvider::Get()->GetDistanceMetric( - views::DISTANCE_RELATED_CONTROL_VERTICAL))); + parent->SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::kHorizontal, gfx::Insets(), + ChromeLayoutProvider::Get()->GetDistanceMetric( + views::DISTANCE_RELATED_CONTROL_VERTICAL))); parent->AddChildView(icon.release()); parent->AddChildView(label.release()); return parent; @@ -123,7 +123,7 @@ void ToolbarActionsBarBubbleViews::Init() { ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); - SetLayoutManager(new views::BoxLayout( + SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::kVertical, gfx::Insets(), provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL)));
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc index 6675fdb..53302df8 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -127,10 +127,9 @@ } void ToolbarView::Init() { - location_bar_ = - new LocationBarView(browser_, browser_->profile(), - browser_->command_controller()->command_updater(), - this, !is_display_mode_normal()); + location_bar_ = new LocationBarView(browser_, browser_->profile(), + browser_->command_controller(), this, + !is_display_mode_normal()); if (!is_display_mode_normal()) { AddChildView(location_bar_); @@ -164,8 +163,8 @@ forward_->set_id(VIEW_ID_FORWARD_BUTTON); forward_->Init(); - reload_ = new ReloadButton(browser_->profile(), - browser_->command_controller()->command_updater()); + reload_ = + new ReloadButton(browser_->profile(), browser_->command_controller()); reload_->set_triggerable_event_flags( ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON); reload_->set_tag(IDC_RELOAD);
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc b/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc index d0af5ab..b7471a3 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc
@@ -198,7 +198,7 @@ gfx::NativeWindow window = browser->window()->GetNativeWindow(); views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window); views::FocusManager* focus_manager = widget->GetFocusManager(); - CommandUpdater* updater = browser->command_controller()->command_updater(); + CommandUpdater* updater = browser->command_controller(); // Send focus to the toolbar as if the user pressed Alt+Shift+T. updater->ExecuteCommand(IDC_FOCUS_TOOLBAR); @@ -261,7 +261,7 @@ } IN_PROC_BROWSER_TEST_F(ToolbarViewTest, ToolbarCycleFocusWithBookmarkBar) { - CommandUpdater* updater = browser()->command_controller()->command_updater(); + CommandUpdater* updater = browser()->command_controller(); updater->ExecuteCommand(IDC_SHOW_BOOKMARK_BAR); BookmarkModel* model =
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.cc b/chrome/browser/ui/views/translate/translate_bubble_view.cc index e3d1a61..78d39b7 100644 --- a/chrome/browser/ui/views/translate/translate_bubble_view.cc +++ b/chrome/browser/ui/views/translate/translate_bubble_view.cc
@@ -189,7 +189,8 @@ } void TranslateBubbleView::Init() { - SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical)); + SetLayoutManager( + std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); should_always_translate_ = model_->ShouldAlwaysTranslate(); if (Use2016Q2UI() && !is_in_incognito_window_) { @@ -569,7 +570,8 @@ } views::View* view = new views::View(); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(view); + views::GridLayout* layout = + view->SetLayoutManager(std::make_unique<views::GridLayout>(view)); using views::GridLayout; @@ -674,7 +676,8 @@ model_->GetLanguageNameAt(model_->GetTargetLanguageIndex()); views::View* view = new views::View(); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(view); + views::GridLayout* layout = + view->SetLayoutManager(std::make_unique<views::GridLayout>(view)); using views::GridLayout; @@ -737,7 +740,8 @@ views::View* TranslateBubbleView::CreateViewAfterTranslate() { views::View* view = new views::View(); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(view); + views::GridLayout* layout = + view->SetLayoutManager(std::make_unique<views::GridLayout>(view)); using views::GridLayout; @@ -798,7 +802,8 @@ views::View* TranslateBubbleView::CreateViewError() { views::View* view = new views::View(); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(view); + views::GridLayout* layout = + view->SetLayoutManager(std::make_unique<views::GridLayout>(view)); using views::GridLayout; @@ -893,7 +898,8 @@ } views::View* view = new views::View(); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(view); + views::GridLayout* layout = + view->SetLayoutManager(std::make_unique<views::GridLayout>(view)); using views::GridLayout;
diff --git a/chrome/browser/ui/views/try_chrome_dialog_win/try_chrome_dialog.cc b/chrome/browser/ui/views/try_chrome_dialog_win/try_chrome_dialog.cc index 31339785..ae1d4a92 100644 --- a/chrome/browser/ui/views/try_chrome_dialog_win/try_chrome_dialog.cc +++ b/chrome/browser/ui/views/try_chrome_dialog_win/try_chrome_dialog.cc
@@ -1026,8 +1026,8 @@ auto contents_view = std::make_unique<ClickableView>(); contents_view->SetBackground(views::CreateSolidBackground(kBackgroundColor)); - views::GridLayout* layout = - views::GridLayout::CreateAndInstall(contents_view.get()); + views::GridLayout* layout = contents_view->SetLayoutManager( + std::make_unique<views::GridLayout>(contents_view.get())); layout->set_minimum_size(gfx::Size(kToastWidth, 0)); views::ColumnSet* columns;
diff --git a/chrome/browser/ui/views/uninstall_view.cc b/chrome/browser/ui/views/uninstall_view.cc index 3109a75c..c350b99 100644 --- a/chrome/browser/ui/views/uninstall_view.cc +++ b/chrome/browser/ui/views/uninstall_view.cc
@@ -47,7 +47,8 @@ using views::ColumnSet; using views::GridLayout; - GridLayout* layout = GridLayout::CreateAndInstall(this); + GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); // Message to confirm uninstallation. int column_set_id = 0;
diff --git a/chrome/browser/ui/views/webshare/webshare_target_picker_view.cc b/chrome/browser/ui/views/webshare/webshare_target_picker_view.cc index 6b485956..5edafb9a 100644 --- a/chrome/browser/ui/views/webshare/webshare_target_picker_view.cc +++ b/chrome/browser/ui/views/webshare/webshare_target_picker_view.cc
@@ -84,11 +84,12 @@ table_model_(base::MakeUnique<TargetPickerTableModel>(targets_)), close_callback_(std::move(close_callback)) { const ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); - views::BoxLayout* layout = new views::BoxLayout( - views::BoxLayout::kVertical, - provider->GetDialogInsetsForContentType(views::TEXT, views::CONTROL), - provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL)); - SetLayoutManager(layout); + views::BoxLayout* layout = + SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::kVertical, + provider->GetDialogInsetsForContentType(views::TEXT, views::CONTROL), + provider->GetDistanceMetric( + views::DISTANCE_RELATED_CONTROL_VERTICAL))); views::Label* overview_label = new views::Label( l10n_util::GetStringUTF16(IDS_WEBSHARE_TARGET_PICKER_LABEL));
diff --git a/chrome/browser/ui/webui/extensions/extension_loader_handler.cc b/chrome/browser/ui/webui/extensions/extension_loader_handler.cc index e3448f3c..03e8062 100644 --- a/chrome/browser/ui/webui/extensions/extension_loader_handler.cc +++ b/chrome/browser/ui/webui/extensions/extension_loader_handler.cc
@@ -55,7 +55,8 @@ ui_ready_(false), weak_ptr_factory_(this) { DCHECK(profile_); - extension_error_reporter_observer_.Add(ExtensionErrorReporter::GetInstance()); + extension_error_reporter_observer_.Add( + extensions::LoadErrorReporter::GetInstance()); } ExtensionLoaderHandler::~ExtensionLoaderHandler() {
diff --git a/chrome/browser/ui/webui/extensions/extension_loader_handler.h b/chrome/browser/ui/webui/extensions/extension_loader_handler.h index a379fe1..a70ab5fb 100644 --- a/chrome/browser/ui/webui/extensions/extension_loader_handler.h +++ b/chrome/browser/ui/webui/extensions/extension_loader_handler.h
@@ -18,7 +18,7 @@ #include "base/memory/weak_ptr.h" #include "base/scoped_observer.h" #include "base/values.h" -#include "chrome/browser/extensions/extension_error_reporter.h" +#include "chrome/browser/extensions/load_error_reporter.h" #include "content/public/browser/reload_type.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_ui_message_handler.h" @@ -35,7 +35,7 @@ // The handler page for the Extension Commands UI overlay. class ExtensionLoaderHandler : public content::WebUIMessageHandler, - public ExtensionErrorReporter::Observer, + public extensions::LoadErrorReporter::Observer, public content::WebContentsObserver { public: using GetManifestErrorCallback = @@ -71,7 +71,7 @@ // Try to load an unpacked extension from the given |file_path|. void LoadUnpackedExtension(const base::FilePath& file_path); - // ExtensionErrorReporter::Observer: + // extensions::LoadErrorReporter::Observer: void OnLoadFailure(content::BrowserContext* browser_context, const base::FilePath& file_path, const std::string& error) override; @@ -101,7 +101,8 @@ // Holds failed paths for load retries. std::vector<base::FilePath> failed_paths_; - ScopedObserver<ExtensionErrorReporter, ExtensionErrorReporter::Observer> + ScopedObserver<extensions::LoadErrorReporter, + extensions::LoadErrorReporter::Observer> extension_error_reporter_observer_; // Set when the chrome://extensions page is fully loaded and the frontend is
diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chrome/browser/ui/webui/extensions/extensions_ui.cc index 32b59b1..3953331 100644 --- a/chrome/browser/ui/webui/extensions/extensions_ui.cc +++ b/chrome/browser/ui/webui/extensions/extensions_ui.cc
@@ -223,6 +223,8 @@ IDS_MD_EXTENSIONS_ITEM_SOURCE_WEBSTORE); source->AddLocalizedString("itemVersion", IDS_MD_EXTENSIONS_ITEM_VERSION); + // TODO(dpapad): Replace this with an Extensions specific string. + source->AddLocalizedString("itemSize", IDS_DIRECTORY_LISTING_SIZE); source->AddLocalizedString("itemAllowOnFileUrls", IDS_EXTENSIONS_ALLOW_FILE_ACCESS); source->AddLocalizedString("itemAllowOnAllSites",
diff --git a/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc b/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc index fc86609..ad17ba5 100644 --- a/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc +++ b/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc
@@ -12,6 +12,7 @@ #include "base/bind.h" #include "base/guid.h" +#include "base/json/json_writer.h" #include "base/memory/ptr_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" @@ -323,8 +324,18 @@ prefetch_service_->GetPrefetchDispatcher()->AddCandidatePrefetchURLs( offline_pages::kSuggestedArticlesNamespace, prefetch_urls); - ResolveJavascriptCallback(base::Value(callback_id), - base::Value("Added candidate URLs.")); + std::string message("Added candidate URLs.\n"); + // Construct a JSON array containing all the URLs. To guard against malicious + // URLs that might contain special characters, we create a ListValue and then + // serialize it into JSON, instead of doing direct string manipulation. + base::ListValue urls; + for (const auto& prefetch_url : prefetch_urls) { + urls.GetList().emplace_back(prefetch_url.url.spec()); + } + std::string json; + base::JSONWriter::Write(urls, &json); + message.append(json); + ResolveJavascriptCallback(base::Value(callback_id), base::Value(message)); } void OfflineInternalsUIMessageHandler::HandleGetOperation(
diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc b/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc index a7cee65..ce5091e 100644 --- a/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc +++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc
@@ -800,6 +800,7 @@ pwg_raster_converter_->bitmap_settings().odd_page_transform); EXPECT_FALSE(pwg_raster_converter_->bitmap_settings().rotate_all_pages); EXPECT_FALSE(pwg_raster_converter_->bitmap_settings().reverse_page_order); + EXPECT_TRUE(pwg_raster_converter_->bitmap_settings().use_color); EXPECT_EQ(printing::kDefaultPdfDpi, pwg_raster_converter_->conversion_settings().dpi); @@ -853,6 +854,7 @@ pwg_raster_converter_->bitmap_settings().odd_page_transform); EXPECT_TRUE(pwg_raster_converter_->bitmap_settings().rotate_all_pages); EXPECT_TRUE(pwg_raster_converter_->bitmap_settings().reverse_page_order); + EXPECT_TRUE(pwg_raster_converter_->bitmap_settings().use_color); EXPECT_EQ(200, // max(vertical_dpi, horizontal_dpi) pwg_raster_converter_->conversion_settings().dpi);
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc index 3be7d9a..7615db39 100644 --- a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc +++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
@@ -71,8 +71,11 @@ } // namespace -LocalPrinterHandlerChromeos::LocalPrinterHandlerChromeos(Profile* profile) - : printers_manager_(CupsPrintersManager::Create(profile)), +LocalPrinterHandlerChromeos::LocalPrinterHandlerChromeos( + Profile* profile, + content::WebContents* preview_web_contents) + : preview_web_contents_(preview_web_contents), + printers_manager_(CupsPrintersManager::Create(profile)), printer_configurer_(chromeos::PrinterConfigurer::Create(profile)), weak_factory_(this) { printers_manager_->Start(); @@ -152,17 +155,6 @@ std::move(cb))); } -void LocalPrinterHandlerChromeos::StartPrint( - const std::string& destination_id, - const std::string& capability, - const base::string16& job_title, - const std::string& ticket_json, - const gfx::Size& page_size, - const scoped_refptr<base::RefCountedBytes>& print_data, - PrintCallback callback) { - NOTREACHED(); -} - void LocalPrinterHandlerChromeos::HandlePrinterSetup( std::unique_ptr<chromeos::Printer> printer, GetCapabilityCallback cb, @@ -203,3 +195,15 @@ // TODO(skau): Open printer settings if this is resolvable. std::move(cb).Run(nullptr); } + +void LocalPrinterHandlerChromeos::StartPrint( + const std::string& destination_id, + const std::string& capability, + const base::string16& job_title, + const std::string& ticket_json, + const gfx::Size& page_size, + const scoped_refptr<base::RefCountedBytes>& print_data, + PrintCallback callback) { + printing::StartLocalPrint(ticket_json, print_data, preview_web_contents_, + std::move(callback)); +}
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.h b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.h index 263bd975..b22c9bc58 100644 --- a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.h +++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.h
@@ -17,11 +17,16 @@ #include "chrome/browser/ui/webui/print_preview/printer_handler.h" #include "chromeos/printing/printer_configuration.h" +namespace content { +class WebContents; +} + class Profile; class LocalPrinterHandlerChromeos : public PrinterHandler { public: - explicit LocalPrinterHandlerChromeos(Profile* profile); + LocalPrinterHandlerChromeos(Profile* profile, + content::WebContents* preview_web_contents); ~LocalPrinterHandlerChromeos() override; // PrinterHandler implementation @@ -31,7 +36,6 @@ GetPrintersDoneCallback done_callback) override; void StartGetCapability(const std::string& printer_name, GetCapabilityCallback cb) override; - // Required by PrinterHandler interface but should never be called. void StartPrint(const std::string& destination_id, const std::string& capability, const base::string16& job_title, @@ -44,6 +48,8 @@ void HandlePrinterSetup(std::unique_ptr<chromeos::Printer> printer, GetCapabilityCallback cb, chromeos::PrinterSetupResult result); + + content::WebContents* const preview_web_contents_; std::unique_ptr<chromeos::CupsPrintersManager> printers_manager_; scoped_refptr<chromeos::PpdProvider> ppd_provider_; std::unique_ptr<chromeos::PrinterConfigurer> printer_configurer_;
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc b/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc index ae37e9025..5d3076d 100644 --- a/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc +++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc
@@ -61,7 +61,9 @@ } // namespace -LocalPrinterHandlerDefault::LocalPrinterHandlerDefault() {} +LocalPrinterHandlerDefault::LocalPrinterHandlerDefault( + content::WebContents* preview_web_contents) + : preview_web_contents_(preview_web_contents) {} LocalPrinterHandlerDefault::~LocalPrinterHandlerDefault() {} @@ -106,5 +108,6 @@ const gfx::Size& page_size, const scoped_refptr<base::RefCountedBytes>& print_data, PrintCallback callback) { - NOTREACHED(); + printing::StartLocalPrint(ticket_json, print_data, preview_web_contents_, + std::move(callback)); }
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_default.h b/chrome/browser/ui/webui/print_preview/local_printer_handler_default.h index de22422..ab07dea 100644 --- a/chrome/browser/ui/webui/print_preview/local_printer_handler_default.h +++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_default.h
@@ -10,14 +10,18 @@ #include "base/callback_forward.h" #include "base/macros.h" -#include "base/memory/weak_ptr.h" #include "base/strings/string16.h" #include "base/values.h" #include "chrome/browser/ui/webui/print_preview/printer_handler.h" +namespace content { +class WebContents; +} + class LocalPrinterHandlerDefault : public PrinterHandler { public: - LocalPrinterHandlerDefault(); + explicit LocalPrinterHandlerDefault( + content::WebContents* preview_web_contents); ~LocalPrinterHandlerDefault() override; // PrinterHandler implementation. @@ -27,7 +31,6 @@ GetPrintersDoneCallback done_callback) override; void StartGetCapability(const std::string& destination_id, GetCapabilityCallback callback) override; - // Required by PrinterHandler interface but should never be called. void StartPrint(const std::string& destination_id, const std::string& capability, const base::string16& job_title, @@ -37,6 +40,8 @@ PrintCallback callback) override; private: + content::WebContents* const preview_web_contents_; + DISALLOW_COPY_AND_ASSIGN(LocalPrinterHandlerDefault); };
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc index d9d9cbdb..7d67cea 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -661,7 +661,7 @@ bool is_cloud_printer = false; bool print_with_privet = false; bool print_with_extension = false; - + bool show_system_dialog = false; bool open_pdf_in_preview = false; #if defined(OS_MACOSX) open_pdf_in_preview = settings->HasKey(printing::kSettingOpenPDFInPreview); @@ -672,26 +672,40 @@ settings->GetBoolean(printing::kSettingPrintWithPrivet, &print_with_privet); settings->GetBoolean(printing::kSettingPrintWithExtension, &print_with_extension); + settings->GetBoolean(printing::kSettingShowSystemDialog, + &show_system_dialog); is_cloud_printer = settings->HasKey(printing::kSettingCloudPrintId); } int page_count = 0; - settings->GetInteger(printing::kSettingPreviewPageCount, &page_count); + if (!settings->GetInteger(printing::kSettingPreviewPageCount, &page_count) || + page_count <= 0) { + RejectJavascriptCallback(base::Value(callback_id), base::Value(-1)); + return; + } -#if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) if (print_with_privet) { +#if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintWithPrivet", page_count); ReportUserActionHistogram(PRINT_WITH_PRIVET); - } #endif - if (print_with_extension) { + } else if (print_with_extension) { UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintWithExtension", page_count); ReportUserActionHistogram(PRINT_WITH_EXTENSION); - } - if (print_to_pdf) { + } else if (print_to_pdf) { UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintToPDF", page_count); ReportUserActionHistogram(PRINT_TO_PDF); + } else if (show_system_dialog) { + UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.SystemDialog", page_count); + ReportUserActionHistogram(FALLBACK_TO_ADVANCED_SETTINGS_DIALOG); + } else if (!open_pdf_in_preview) { + UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintToPrinter", page_count); + ReportUserActionHistogram(PRINT_TO_PRINTER); + } else if (is_cloud_printer) { + UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintToCloudPrint", + page_count); + ReportUserActionHistogram(PRINT_WITH_CLOUD_PRINT); } scoped_refptr<base::RefCountedBytes> data; @@ -707,112 +721,50 @@ DCHECK(data->size()); DCHECK(data->front()); - if (print_with_privet || print_with_extension || print_to_pdf) { - std::string destination_id; - std::string print_ticket; - std::string capabilities; - int width = 0; - int height = 0; - if (!print_to_pdf && - (!settings->GetString(printing::kSettingDeviceName, &destination_id) || - !settings->GetString(printing::kSettingTicket, &print_ticket) || - !settings->GetString(printing::kSettingCapabilities, &capabilities) || - !settings->GetInteger(printing::kSettingPageWidth, &width) || - !settings->GetInteger(printing::kSettingPageHeight, &height) || - width <= 0 || height <= 0)) { - NOTREACHED(); - RejectJavascriptCallback( - base::Value(callback_id), - print_with_privet ? base::Value(-1) : base::Value("FAILED")); - return; - } - - PrinterType type = PrinterType::kPdfPrinter; - if (print_with_extension) - type = PrinterType::kExtensionPrinter; - else if (print_with_privet) - type = PrinterType::kPrivetPrinter; - PrinterHandler* handler = GetPrinterHandler(type); - handler->StartPrint( - destination_id, capabilities, print_preview_ui()->initiator_title(), - print_ticket, gfx::Size(width, height), data, - base::BindOnce(&PrintPreviewHandler::OnPrintResult, - weak_factory_.GetWeakPtr(), callback_id)); - return; - } - if (is_cloud_printer) { - UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintToCloudPrint", - page_count); - ReportUserActionHistogram(PRINT_WITH_CLOUD_PRINT); - // Does not send the title like the printer handler types above, because JS - // already has the document title from the initial settings. + // Does not send the title like the other printer handler types below, + // because JS already has the document title from the initial settings. SendCloudPrintJob(callback_id, data.get()); return; } -#if BUILDFLAG(ENABLE_BASIC_PRINTING) - bool system_dialog = false; - settings->GetBoolean(printing::kSettingShowSystemDialog, &system_dialog); - if (system_dialog) { - UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.SystemDialog", page_count); - ReportUserActionHistogram(FALLBACK_TO_ADVANCED_SETTINGS_DIALOG); - } else { - UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintToPrinter", page_count); - ReportUserActionHistogram(PRINT_TO_PRINTER); + std::string destination_id; + std::string print_ticket; + std::string capabilities; + int width = 0; + int height = 0; + if ((print_with_privet || print_with_extension) && + (!settings->GetString(printing::kSettingDeviceName, &destination_id) || + !settings->GetString(printing::kSettingTicket, &print_ticket) || + !settings->GetString(printing::kSettingCapabilities, &capabilities) || + !settings->GetInteger(printing::kSettingPageWidth, &width) || + !settings->GetInteger(printing::kSettingPageHeight, &height) || + width <= 0 || height <= 0)) { + NOTREACHED(); + RejectJavascriptCallback( + base::Value(callback_id), + print_with_privet ? base::Value(-1) : base::Value("FAILED")); + return; } - WebContents* initiator = GetInitiator(); - if (initiator) { - // Save initiator IDs. PrintMsg_PrintForPrintPreview below should cause - // the renderer to send PrintHostMsg_UpdatePrintSettings and trigger - // PrintingMessageFilter::OnUpdatePrintSettings(), which needs this info. - auto* main_render_frame = initiator->GetMainFrame(); - settings->SetInteger(printing::kPreviewInitiatorHostId, - main_render_frame->GetProcess()->GetID()); - settings->SetInteger(printing::kPreviewInitiatorRoutingId, - main_render_frame->GetRoutingID()); - } - - // Set ID to know whether printing is for preview. - settings->SetInteger(printing::kPreviewUIID, - print_preview_ui()->GetIDForPrintPreviewUI()); - - // Save the settings and notify print preview. Print preview will respond - // with a "hidePreviewDialog" message, and then the message can be sent to - // the renderer in HandleHidePreview(). - settings_ = std::move(settings); - ResolveJavascriptCallback(base::Value(callback_id), base::Value()); - -#else - NOTREACHED(); -#endif // BUILDFLAG(ENABLE_BASIC_PRINTING) + PrinterType type = PrinterType::kLocalPrinter; + if (print_with_extension) + type = PrinterType::kExtensionPrinter; + else if (print_with_privet) + type = PrinterType::kPrivetPrinter; + else if (print_to_pdf) + type = PrinterType::kPdfPrinter; + PrinterHandler* handler = GetPrinterHandler(type); + handler->StartPrint( + destination_id, capabilities, print_preview_ui()->initiator_title(), + type == PrinterType::kLocalPrinter ? json_str : print_ticket, + gfx::Size(width, height), data, + base::BindOnce(&PrintPreviewHandler::OnPrintResult, + weak_factory_.GetWeakPtr(), callback_id)); } void PrintPreviewHandler::HandleHidePreview(const base::ListValue* /*args*/) { print_preview_ui()->OnHidePreviewDialog(); -#if BUILDFLAG(ENABLE_BASIC_PRINTING) - if (settings_) { - // Print preview is responding to a resolution of "print" promise. Send the - // print message to the renderer. - RenderFrameHost* rfh = preview_web_contents()->GetMainFrame(); - rfh->Send( - new PrintMsg_PrintForPrintPreview(rfh->GetRoutingID(), *settings_)); - settings_.reset(); - - // Clear the initiator so that it can open a new print preview dialog, while - // the current print preview dialog is still handling its print job. - WebContents* initiator = GetInitiator(); - ClearInitiatorDetails(); - - // Since the preview dialog is hidden and not closed, we need to make this - // call. - if (initiator) { - auto* print_view_manager = PrintViewManager::FromWebContents(initiator); - print_view_manager->PrintPreviewDone(); - } - } -#endif } void PrintPreviewHandler::HandleCancelPendingPrintRequest( @@ -1253,8 +1205,8 @@ } if (printer_type == PrinterType::kLocalPrinter) { if (!local_printer_handler_) { - local_printer_handler_ = - PrinterHandler::CreateForLocalPrinters(Profile::FromWebUI(web_ui())); + local_printer_handler_ = PrinterHandler::CreateForLocalPrinters( + preview_web_contents(), Profile::FromWebUI(web_ui())); } return local_printer_handler_.get(); }
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.h b/chrome/browser/ui/webui/print_preview/print_preview_handler.h index 7552bb23..894f5e9a 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler.h +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.h
@@ -322,12 +322,6 @@ base::queue<std::string> preview_callbacks_; -#if BUILDFLAG(ENABLE_BASIC_PRINTING) - // Print settings to use in the local print request to send when - // HandleHidePreview() is called. - std::unique_ptr<base::DictionaryValue> settings_; -#endif - base::WeakPtrFactory<PrintPreviewHandler> weak_factory_; DISALLOW_COPY_AND_ASSIGN(PrintPreviewHandler);
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc index 111c46e..382461c3 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc
@@ -82,6 +82,7 @@ base::Value GetPrintTicket(printing::PrinterType type, bool cloud) { bool is_privet_printer = !cloud && type == printing::kPrivetPrinter; bool is_extension_printer = !cloud && type == printing::kExtensionPrinter; + base::Value ticket(base::Value::Type::DICTIONARY); // Letter @@ -597,8 +598,8 @@ handler()->HandlePrint(list_args.get()); // Verify correct PrinterHandler was called or that no handler was requested - // for local and cloud printers. - if (cloud || type == printing::kLocalPrinter) { + // for cloud printers. + if (cloud) { EXPECT_TRUE(handler()->NotCalled()); } else { EXPECT_TRUE(handler()->CalledOnlyForType(type)); @@ -608,18 +609,6 @@ const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); CheckWebUIResponse(data, callback_id_in, true); - // For local printers, the Print Preview UI will respond to the resolution - // by sending a "hidePreview" message, which should prompt an IPC message - // to the renderer. - if (type == printing::kLocalPrinter) { - base::Value hide_args(base::Value::Type::LIST); - std::unique_ptr<base::ListValue> hide_args_ptr = base::ListValue::From( - base::Value::ToUniquePtrValue(std::move(hide_args))); - handler()->HandleHidePreview(hide_args_ptr.get()); - EXPECT_TRUE(preview_sink().GetUniqueMessageMatching( - PrintMsg_PrintForPrintPreview::ID)); - } - // For cloud print, should also get the encoded data back as a string. if (cloud) { std::string print_data;
diff --git a/chrome/browser/ui/webui/print_preview/printer_capabilities.cc b/chrome/browser/ui/webui/print_preview/printer_capabilities.cc index 33b8bef6..e8d594e1 100644 --- a/chrome/browser/ui/webui/print_preview/printer_capabilities.cc +++ b/chrome/browser/ui/webui/print_preview/printer_capabilities.cc
@@ -9,18 +9,25 @@ #include <utility> #include <vector> +#include "base/json/json_reader.h" #include "base/logging.h" #include "base/memory/ptr_util.h" +#include "base/memory/ref_counted_memory.h" #include "base/stl_util.h" #include "base/strings/string_piece.h" #include "base/threading/thread_restrictions.h" #include "base/values.h" #include "build/build_config.h" +#include "chrome/browser/printing/print_preview_dialog_controller.h" +#include "chrome/browser/printing/print_view_manager.h" +#include "chrome/browser/ui/webui/print_preview/print_preview_ui.h" #include "chrome/browser/ui/webui/print_preview/printer_handler.h" #include "chrome/common/cloud_print/cloud_print_cdd_conversion.h" #include "chrome/common/crash_keys.h" +#include "content/public/browser/render_frame_host.h" #include "printing/backend/print_backend.h" #include "printing/backend/print_backend_consts.h" +#include "printing/page_range.h" #if defined(OS_WIN) #include "base/strings/string_split.h" @@ -161,6 +168,10 @@ return false; } +void SystemDialogDone(const base::Value& error) { + // intentional no-op +} + } // namespace std::pair<std::string, std::string> GetPrinterNameAndDescription( @@ -281,4 +292,42 @@ return validated_cdd; } +void StartLocalPrint(const std::string& ticket_json, + const scoped_refptr<base::RefCountedBytes>& print_data, + content::WebContents* preview_web_contents, + PrinterHandler::PrintCallback callback) { + std::unique_ptr<base::DictionaryValue> job_settings = + base::DictionaryValue::From(base::JSONReader::Read(ticket_json)); + if (!job_settings) { + std::move(callback).Run(base::Value("Invalid settings")); + return; + } + + // Get print view manager. + PrintPreviewDialogController* dialog_controller = + PrintPreviewDialogController::GetInstance(); + content::WebContents* initiator = + dialog_controller ? dialog_controller->GetInitiator(preview_web_contents) + : nullptr; + PrintViewManager* print_view_manager = + PrintViewManager::FromWebContents(initiator); + if (!print_view_manager) { + std::move(callback).Run(base::Value("Initiator closed")); + return; + } + + bool system_dialog = false; + job_settings->GetBoolean(printing::kSettingShowSystemDialog, &system_dialog); + bool open_in_pdf = false; + job_settings->GetBoolean(printing::kSettingOpenPDFInPreview, &open_in_pdf); + if (system_dialog || open_in_pdf) { + // Run the callback early, or the modal dialogs will prevent the preview + // from closing until they do. + std::move(callback).Run(base::Value()); + callback = base::BindOnce(&SystemDialogDone); + } + print_view_manager->PrintForPrintPreview(std::move(job_settings), print_data, + preview_web_contents->GetMainFrame(), + std::move(callback)); +} } // namespace printing
diff --git a/chrome/browser/ui/webui/print_preview/printer_capabilities.h b/chrome/browser/ui/webui/print_preview/printer_capabilities.h index 47bd80f..04dd0fee 100644 --- a/chrome/browser/ui/webui/print_preview/printer_capabilities.h +++ b/chrome/browser/ui/webui/print_preview/printer_capabilities.h
@@ -13,6 +13,10 @@ #include "chrome/browser/ui/webui/print_preview/printer_handler.h" #include "printing/backend/print_backend.h" +namespace content { +class WebContents; +} + namespace printing { struct PrinterBasicInfo; @@ -50,6 +54,13 @@ // and remove any lists/options that are empty or only contain null values. std::unique_ptr<base::DictionaryValue> ValidateCddForPrintPreview( const base::DictionaryValue& cdd); + +// Starts a local print of |print_data| with print settings dictionary +// |ticket_json|. Runs |callback| on failure or success. +void StartLocalPrint(const std::string& ticket_json, + const scoped_refptr<base::RefCountedBytes>& print_data, + content::WebContents* preview_web_contents, + PrinterHandler::PrintCallback callback); } // namespace printing #endif // CHROME_BROWSER_UI_WEBUI_PRINT_PREVIEW_PRINTER_CAPABILITIES_H_
diff --git a/chrome/browser/ui/webui/print_preview/printer_handler.cc b/chrome/browser/ui/webui/print_preview/printer_handler.cc index 43126964a..f499074 100644 --- a/chrome/browser/ui/webui/print_preview/printer_handler.cc +++ b/chrome/browser/ui/webui/print_preview/printer_handler.cc
@@ -27,11 +27,13 @@ // static std::unique_ptr<PrinterHandler> PrinterHandler::CreateForLocalPrinters( + content::WebContents* preview_web_contents, Profile* profile) { #if defined(OS_CHROMEOS) - return base::MakeUnique<LocalPrinterHandlerChromeos>(profile); + return base::MakeUnique<LocalPrinterHandlerChromeos>(profile, + preview_web_contents); #else - return base::MakeUnique<LocalPrinterHandlerDefault>(); + return base::MakeUnique<LocalPrinterHandlerDefault>(preview_web_contents); #endif }
diff --git a/chrome/browser/ui/webui/print_preview/printer_handler.h b/chrome/browser/ui/webui/print_preview/printer_handler.h index 96a2fcbc..6231baf 100644 --- a/chrome/browser/ui/webui/print_preview/printer_handler.h +++ b/chrome/browser/ui/webui/print_preview/printer_handler.h
@@ -71,6 +71,7 @@ printing::StickySettings* sticky_settings); static std::unique_ptr<PrinterHandler> CreateForLocalPrinters( + content::WebContents* preview_web_contents, Profile* profile); #if BUILDFLAG(ENABLE_SERVICE_DISCOVERY)
diff --git a/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc index 28d34b8..bbf2fa1 100644 --- a/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc
@@ -125,16 +125,12 @@ // Simulate an external keyboard being connected. We should assume there's a // Caps Lock key now. input_device_client_test_api_.SetKeyboardDevices(std::vector<ui::InputDevice>{ - {1, ui::INPUT_DEVICE_EXTERNAL, "external keyboard"}}); - input_device_client_test_api_ - .NotifyObserversKeyboardDeviceConfigurationChanged(); + {2, ui::INPUT_DEVICE_EXTERNAL, "external keyboard"}}); EXPECT_TRUE(HasCapsLock()); EXPECT_FALSE(HasDiamondKey()); // Disconnect the external keyboard and check that the key goes away. input_device_client_test_api_.SetKeyboardDevices({}); - input_device_client_test_api_ - .NotifyObserversKeyboardDeviceConfigurationChanged(); EXPECT_FALSE(HasCapsLock()); EXPECT_FALSE(HasDiamondKey()); }
diff --git a/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc b/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc index 38cb47f..3aaa3065 100644 --- a/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/webui/settings/chromeos/internet_handler.h" +#include <memory> #include <vector> #include "base/bind.h" @@ -35,6 +36,10 @@ const char kConfigureNetworkMessage[] = "configureNetwork"; const char kRequestArcVpnProviders[] = "requestArcVpnProviders"; const char kSendArcVpnProviders[] = "sendArcVpnProviders"; +const char kRequestGmsCoreNotificationsDisabledDeviceNames[] = + "requestGmsCoreNotificationsDisabledDeviceNames"; +const char kSendGmsCoreNotificationsDisabledDeviceNames[] = + "sendGmsCoreNotificationsDisabledDeviceNames"; std::string ServicePathFromGuid(const std::string& guid) { const NetworkState* network = @@ -89,6 +94,11 @@ kRequestArcVpnProviders, base::Bind(&InternetHandler::RequestArcVpnProviders, base::Unretained(this))); + web_ui()->RegisterMessageCallback( + kRequestGmsCoreNotificationsDisabledDeviceNames, + base::Bind( + &InternetHandler::RequestGmsCoreNotificationsDisabledDeviceNames, + base::Unretained(this))); } void InternetHandler::OnJavascriptAllowed() {} @@ -205,6 +215,16 @@ SetArcVpnProviders(arc_vpn_provider_manager_->GetArcVpnProviders()); } +void InternetHandler::RequestGmsCoreNotificationsDisabledDeviceNames( + const base::ListValue* args) { + // TODO(khorimoto): Send an actual list of device names. Currently, an empty + // list is sent. See crbug.com/765966. + std::vector<std::string> device_names; + + AllowJavascript(); + SetGmsCoreNotificationsDisabledDeviceNames(device_names); +} + void InternetHandler::SetArcVpnProviders( const std::vector< std::unique_ptr<app_list::ArcVpnProviderManager::ArcVpnProvider>>& @@ -228,6 +248,28 @@ FireWebUIListener(kSendArcVpnProviders, arc_vpn_providers_value); } +void InternetHandler::SetGmsCoreNotificationsDisabledDeviceNames( + const std::vector<std::string>& device_names) { + device_names_without_notifications_.clear(); + for (const auto& device_name : device_names) { + device_names_without_notifications_.emplace_back( + std::make_unique<base::Value>(device_name)); + } + SendGmsCoreNotificationsDisabledDeviceNames(); +} + +void InternetHandler::SendGmsCoreNotificationsDisabledDeviceNames() { + if (!IsJavascriptAllowed()) + return; + + base::ListValue device_names_value; + for (const auto& device_name : device_names_without_notifications_) + device_names_value.GetList().push_back(device_name->Clone()); + + FireWebUIListener(kSendGmsCoreNotificationsDisabledDeviceNames, + device_names_value); +} + gfx::NativeWindow InternetHandler::GetNativeWindow() const { return web_ui()->GetWebContents()->GetTopLevelNativeWindow(); }
diff --git a/chrome/browser/ui/webui/settings/chromeos/internet_handler.h b/chrome/browser/ui/webui/settings/chromeos/internet_handler.h index 9b84562..cc233c0 100644 --- a/chrome/browser/ui/webui/settings/chromeos/internet_handler.h +++ b/chrome/browser/ui/webui/settings/chromeos/internet_handler.h
@@ -45,6 +45,8 @@ void AddNetwork(const base::ListValue* args); void ConfigureNetwork(const base::ListValue* args); void RequestArcVpnProviders(const base::ListValue* args); + void RequestGmsCoreNotificationsDisabledDeviceNames( + const base::ListValue* args); // Sets list of Arc Vpn providers. void SetArcVpnProviders( @@ -55,11 +57,21 @@ // Sends list of Arc Vpn providers to Chrome://settings. void SendArcVpnProviders(); + // Sets list of names of devices whose "Google Play Services" notifications + // are disabled. + void SetGmsCoreNotificationsDisabledDeviceNames( + const std::vector<std::string>& device_names); + + // Sends the list of names. + void SendGmsCoreNotificationsDisabledDeviceNames(); + gfx::NativeWindow GetNativeWindow() const; std::map<std::string, std::unique_ptr<base::DictionaryValue>> arc_vpn_providers_; + std::vector<std::unique_ptr<base::Value>> device_names_without_notifications_; + Profile* const profile_; app_list::ArcVpnProviderManager* arc_vpn_provider_manager_;
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 f8e08de..550ce30b 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
@@ -1047,6 +1047,20 @@ {"networkOutOfRange", IDS_SETTINGS_INTERNET_WIFI_NETWORK_OUT_OF_RANGE}, {"tetherPhoneOutOfRange", IDS_SETTINGS_INTERNET_TETHER_PHONE_OUT_OF_RANGE}, + {"gmscoreNotificationsTitle", + IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_TITLE}, + {"gmscoreNotificationsOneDeviceSubtitle", + IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_ONE_DEVICE_SUBTITLE}, + {"gmscoreNotificationsTwoDevicesSubtitle", + IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_TWO_DEVICES_SUBTITLE}, + {"gmscoreNotificationsManyDevicesSubtitle", + IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_MANY_DEVICES_SUBTITLE}, + {"gmscoreNotificationsFirstStep", + IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_FIRST_STEP}, + {"gmscoreNotificationsSecondStep", + IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_SECOND_STEP}, + {"gmscoreNotificationsThirdStep", + IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_THIRD_STEP}, {"tetherConnectionDialogTitle", IDS_SETTINGS_INTERNET_TETHER_CONNECTION_DIALOG_TITLE}, {"tetherConnectionAvailableDeviceTitle",
diff --git a/chrome/browser/vr/ui_input_manager.cc b/chrome/browser/vr/ui_input_manager.cc index 21d7a9d8..9e13b3bc 100644 --- a/chrome/browser/vr/ui_input_manager.cc +++ b/chrome/browser/vr/ui_input_manager.cc
@@ -91,30 +91,14 @@ reticle_model->target_element_id = 0; reticle_model->target_local_point = kInvalidTargetPoint; GetVisualTargetElement(controller_model, reticle_model); - - UiElement* target_element = nullptr; - // TODO(vollick): this should be replaced with a formal notion of input - // capture. - if (input_locked_element_id_) { - target_element = scene_->GetUiElementById(input_locked_element_id_); - if (target_element) { - HitTestRequest request; - request.ray_origin = kOrigin; - request.ray_target = reticle_model->target_point; - request.max_distance_to_plane = 2 * scene_->background_distance(); - HitTestResult result; - target_element->HitTest(request, &result); - reticle_model->target_local_point = result.local_hit_point; - if (result.type == HitTestResult::Type::kNone) { - reticle_model->target_local_point = kInvalidTargetPoint; - } - } - } else if (!in_scroll_ && !in_click_) { - // TODO(vollick): support multiple dispatch. We may want to, for example, - // dispatch raw events to several elements we hit (imagine nested horizontal - // and vertical scrollers). Currently, we only dispatch to one "winner". - target_element = scene_->GetUiElementById(reticle_model->target_element_id); - if (target_element && IsScrollEvent(*gesture_list)) { + // TODO(vollick): support multiple dispatch. We may want to, for example, + // dispatch raw events to several elements we hit (imagine nested horizontal + // and vertical scrollers). Currently, we only dispatch to one "winner". + UiElement* target_element = + scene_->GetUiElementById(reticle_model->target_element_id); + if (target_element) { + if (IsScrollEvent(*gesture_list) && !input_capture_element_id_) { + DCHECK(!in_scroll_ && !in_click_); UiElement* ancestor = target_element; while (!ancestor->scrollable() && ancestor->parent()) { ancestor = ancestor->parent(); @@ -125,14 +109,30 @@ } } - SendFlingCancel(gesture_list, reticle_model->target_local_point); + auto element_local_point = reticle_model->target_local_point; + if (input_capture_element_id_) { + auto* captured = scene_->GetUiElementById(input_capture_element_id_); + if (captured) { + HitTestRequest request; + request.ray_origin = kOrigin; + request.ray_target = reticle_model->target_point; + request.max_distance_to_plane = 2 * scene_->background_distance(); + HitTestResult result; + captured->HitTest(request, &result); + element_local_point = result.local_hit_point; + if (result.type == HitTestResult::Type::kNone) { + element_local_point = kInvalidTargetPoint; + } + } + } + + SendFlingCancel(gesture_list, element_local_point); // For simplicity, don't allow scrolling while clicking until we need to. if (!in_click_) { - SendScrollEnd(gesture_list, reticle_model->target_local_point, + SendScrollEnd(gesture_list, element_local_point, controller_model.touchpad_button_state); - if (!SendScrollBegin(target_element, gesture_list, - reticle_model->target_local_point)) { - SendScrollUpdate(gesture_list, reticle_model->target_local_point); + if (!SendScrollBegin(target_element, gesture_list, element_local_point)) { + SendScrollUpdate(gesture_list, element_local_point); } } @@ -141,23 +141,13 @@ if (in_scroll_) { return; } - SendHoverLeave(target_element); - if (!SendHoverEnter(target_element, reticle_model->target_local_point)) { - SendHoverMove(reticle_model->target_local_point); - } + + SendHoverEvents(target_element, reticle_model->target_local_point); SendButtonDown(target_element, reticle_model->target_local_point, controller_model.touchpad_button_state); - if (SendButtonUp(reticle_model->target_local_point, - controller_model.touchpad_button_state)) { - target_element = scene_->GetUiElementById(reticle_model->target_element_id); - SendHoverLeave(target_element); - SendHoverEnter(target_element, reticle_model->target_local_point); - } + SendButtonUp(element_local_point, controller_model.touchpad_button_state); - previous_button_state_ = - (controller_model.touchpad_button_state == ButtonState::CLICKED) - ? ButtonState::UP - : controller_model.touchpad_button_state; + previous_button_state_ = controller_model.touchpad_button_state; } void UiInputManager::SendFlingCancel(GestureList* gesture_list, @@ -186,12 +176,11 @@ if (!in_scroll_) { return; } - DCHECK_GT(input_locked_element_id_, 0); - UiElement* element = scene_->GetUiElementById(input_locked_element_id_); + DCHECK_GT(input_capture_element_id_, 0); + UiElement* element = scene_->GetUiElementById(input_capture_element_id_); if (previous_button_state_ != button_state && - (button_state == ButtonState::DOWN || - button_state == ButtonState::CLICKED)) { + button_state == ButtonState::DOWN) { DCHECK_GT(gesture_list->size(), 0LU); DCHECK_EQ(gesture_list->front()->GetType(), blink::WebInputEvent::kGestureScrollEnd); @@ -214,13 +203,13 @@ } else { DCHECK_EQ(gesture_list->front()->GetType(), blink::WebInputEvent::kGestureFlingStart); - fling_target_id_ = input_locked_element_id_; + fling_target_id_ = input_capture_element_id_; if (element) { element->OnFlingStart(std::move(gesture_list->front()), target_point); } } gesture_list->erase(gesture_list->begin()); - input_locked_element_id_ = 0; + input_capture_element_id_ = 0; in_scroll_ = false; } @@ -238,7 +227,7 @@ blink::WebInputEvent::kGestureScrollBegin)) { return false; } - input_locked_element_id_ = target->id(); + input_capture_element_id_ = target->id(); in_scroll_ = true; target->OnScrollBegin(std::move(gesture_list->front()), target_point); gesture_list->erase(gesture_list->begin()); @@ -250,13 +239,13 @@ if (!in_scroll_) { return; } - DCHECK(input_locked_element_id_); + DCHECK(input_capture_element_id_); if (gesture_list->empty() || (gesture_list->front()->GetType() != blink::WebInputEvent::kGestureScrollUpdate)) { return; } // Scrolling currently only supported on content window. - UiElement* element = scene_->GetUiElementById(input_locked_element_id_); + UiElement* element = scene_->GetUiElementById(input_capture_element_id_); if (element) { DCHECK(element->scrollable()); element->OnScrollUpdate(std::move(gesture_list->front()), target_point); @@ -264,47 +253,38 @@ gesture_list->erase(gesture_list->begin()); } -void UiInputManager::SendHoverLeave(UiElement* target) { - if (!hover_target_id_) { - return; - } +void UiInputManager::SendHoverEvents(UiElement* target, + const gfx::PointF& target_point) { if (target && target->id() == hover_target_id_) { + SendMove(target, target_point); return; } - UiElement* element = scene_->GetUiElementById(hover_target_id_); - if (element) { - element->OnHoverLeave(); + + UiElement* prev_hovered = scene_->GetUiElementById(hover_target_id_); + if (prev_hovered) { + prev_hovered->OnHoverLeave(); } hover_target_id_ = 0; + if (target) { + target->OnHoverEnter(target_point); + hover_target_id_ = target->id(); + } } -bool UiInputManager::SendHoverEnter(UiElement* target, - const gfx::PointF& target_point) { - if (!target || target->id() == hover_target_id_) { - return false; - } - target->OnHoverEnter(target_point); - hover_target_id_ = target->id(); - return true; -} - -void UiInputManager::SendHoverMove(const gfx::PointF& target_point) { - if (!hover_target_id_) { - return; - } - UiElement* element = scene_->GetUiElementById(hover_target_id_); +void UiInputManager::SendMove(UiElement* element, + const gfx::PointF& target_point) { + DCHECK(element); if (!element) { return; } - - // TODO(mthiesse, vollick): Content is currently way too sensitive to mouse - // moves for how noisy the controller is. It's almost impossible to click a - // link without unintentionally starting a drag event. For this reason we - // disable mouse moves, only delivering a down and up event. + // TODO(mthiesse, vollick): Content is currently way too sensitive to + // mouse moves for how noisy the controller is. It's almost impossible + // to click a link without unintentionally starting a drag event. For + // this reason we disable mouse moves, only delivering a down and up + // event. if (element->name() == kContentQuad && in_click_) { return; } - element->OnMove(target_point); } @@ -315,16 +295,15 @@ return; } if (previous_button_state_ == button_state || - (button_state != ButtonState::DOWN && - button_state != ButtonState::CLICKED)) { + button_state != ButtonState::DOWN) { return; } in_click_ = true; if (target) { target->OnButtonDown(target_point); - input_locked_element_id_ = target->id(); + input_capture_element_id_ = target->id(); } else { - input_locked_element_id_ = 0; + input_capture_element_id_ = 0; } } @@ -334,15 +313,14 @@ return false; } if (previous_button_state_ == button_state || - (button_state != ButtonState::UP && - button_state != ButtonState::CLICKED)) { + button_state != ButtonState::UP) { return false; } in_click_ = false; - if (!input_locked_element_id_) { + if (!input_capture_element_id_) { return false; } - UiElement* element = scene_->GetUiElementById(input_locked_element_id_); + UiElement* element = scene_->GetUiElementById(input_capture_element_id_); if (element) { element->OnButtonUp(target_point); // Clicking outside of the focused element causes it to lose focus. @@ -351,7 +329,7 @@ } } - input_locked_element_id_ = 0; + input_capture_element_id_ = 0; return true; }
diff --git a/chrome/browser/vr/ui_input_manager.h b/chrome/browser/vr/ui_input_manager.h index 1496fc2..5ccbfa3b 100644 --- a/chrome/browser/vr/ui_input_manager.h +++ b/chrome/browser/vr/ui_input_manager.h
@@ -35,8 +35,6 @@ enum ButtonState { UP, // The button is released. DOWN, // The button is pressed. - CLICKED, // Since the last update the button has been pressed and released. - // The button is released now. }; // When testing, it can be useful to hit test directly along the laser. @@ -80,9 +78,9 @@ const gfx::PointF& target_point); void SendScrollUpdate(GestureList* gesture_list, const gfx::PointF& target_point); - void SendHoverLeave(UiElement* target); - bool SendHoverEnter(UiElement* target, const gfx::PointF& target_point); - void SendHoverMove(const gfx::PointF& target_point); + + void SendHoverEvents(UiElement* target, const gfx::PointF& target_point); + void SendMove(UiElement* element, const gfx::PointF& target_point); void SendButtonDown(UiElement* target, const gfx::PointF& target_point, ButtonState button_state); @@ -100,10 +98,10 @@ // independently and we should only cancel flings on the relevant element // when we do cancel flings. int fling_target_id_ = 0; - int input_locked_element_id_ = 0; + int input_capture_element_id_ = 0; + int focused_element_id_ = 0; bool in_click_ = false; bool in_scroll_ = false; - int focused_element_id_ = 0; HitTestStrategy hit_test_strategy_ = HitTestStrategy::PROJECT_TO_WORLD_ORIGIN;
diff --git a/chrome/browser/vr/ui_input_manager_unittest.cc b/chrome/browser/vr/ui_input_manager_unittest.cc index 13015f81..cc071ee 100644 --- a/chrome/browser/vr/ui_input_manager_unittest.cc +++ b/chrome/browser/vr/ui_input_manager_unittest.cc
@@ -34,8 +34,6 @@ constexpr UiInputManager::ButtonState kUp = UiInputManager::ButtonState::UP; constexpr UiInputManager::ButtonState kDown = UiInputManager::ButtonState::DOWN; -constexpr UiInputManager::ButtonState kClick = - UiInputManager::ButtonState::CLICKED; class MockRect : public Rect { public: @@ -257,22 +255,17 @@ HandleInput(kForwardVector, kUp); Mock::VerifyAndClearExpectations(p_element); - // Perform a click (both press and release) on the element. - EXPECT_CALL(*p_element, OnMove(_)); - EXPECT_CALL(*p_element, OnButtonDown(_)); - EXPECT_CALL(*p_element, OnButtonUp(_)); - HandleInput(kForwardVector, kClick); - Mock::VerifyAndClearExpectations(p_element); - // Move off of the element. EXPECT_CALL(*p_element, OnHoverLeave()); HandleInput(kBackwardVector, kUp); Mock::VerifyAndClearExpectations(p_element); // Press while not on the element, move over the element, move away, then - // release. The element should receive no input. + // release. The element should receive hover events. HandleInput(kBackwardVector, kDown); + EXPECT_CALL(*p_element, OnHoverEnter(_)); HandleInput(kForwardVector, kDown); + EXPECT_CALL(*p_element, OnHoverLeave()); HandleInput(kBackwardVector, kUp); Mock::VerifyAndClearExpectations(p_element); @@ -280,12 +273,10 @@ EXPECT_CALL(*p_element, OnHoverEnter(_)); EXPECT_CALL(*p_element, OnButtonDown(_)); HandleInput(kForwardVector, kDown); - EXPECT_CALL(*p_element, OnMove(_)); + EXPECT_CALL(*p_element, OnHoverLeave()); HandleInput(kBackwardVector, kDown); Mock::VerifyAndClearExpectations(p_element); - EXPECT_CALL(*p_element, OnMove(_)); EXPECT_CALL(*p_element, OnButtonUp(_)); - EXPECT_CALL(*p_element, OnHoverLeave()); HandleInput(kBackwardVector, kUp); Mock::VerifyAndClearExpectations(p_element); } @@ -297,17 +288,22 @@ StrictMock<MockRect>* p_front_element = CreateAndAddMockElement(-5.f); StrictMock<MockRect>* p_back_element = CreateAndAddMockElement(5.f); + // TODO(ymalik): We should test verify that the functions called on the + // element are in the element's local coordinate space, but that would require + // writing a matcher for gfx::Point3F. // Press on an element, move away, then release. EXPECT_CALL(*p_front_element, OnHoverEnter(_)); EXPECT_CALL(*p_front_element, OnButtonDown(_)); - EXPECT_CALL(*p_front_element, OnMove(_)); - EXPECT_CALL(*p_front_element, OnMove(_)); - EXPECT_CALL(*p_front_element, OnButtonUp(_)); + HandleInput(kForwardVector, kDown); EXPECT_CALL(*p_front_element, OnHoverLeave()); EXPECT_CALL(*p_back_element, OnHoverEnter(_)); - HandleInput(kForwardVector, kDown); HandleInput(kBackwardVector, kDown); + EXPECT_CALL(*p_back_element, OnMove(_)); + EXPECT_CALL(*p_front_element, OnButtonUp(_)); HandleInput(kBackwardVector, kUp); + EXPECT_CALL(*p_back_element, OnHoverLeave()); + EXPECT_CALL(*p_front_element, OnHoverEnter(_)); + HandleInput(kForwardVector, kUp); } // Test that input is tolerant of disappearing elements.
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn index 275fd461..093a4e1 100644 --- a/chrome/common/BUILD.gn +++ b/chrome/common/BUILD.gn
@@ -213,7 +213,6 @@ "//chrome/app/theme:theme_resources", "//chrome/common:constants", "//chrome/common/net", - "//chrome/common/printing:interfaces", "//chrome/common/profiling", "//chrome/installer/util:with_no_strings", "//components/cast_certificate",
diff --git a/chrome/common/extensions/api/autotest_private.idl b/chrome/common/extensions/api/autotest_private.idl index f14ba14..05b97314 100644 --- a/chrome/common/extensions/api/autotest_private.idl +++ b/chrome/common/extensions/api/autotest_private.idl
@@ -65,6 +65,13 @@ }; callback NotificationArrayCallback = void (Notification[] notifications); + dictionary Printer { + DOMString printerName; + DOMString printerId; + DOMString printerType; + }; + callback PrinterArrayCallback = void (Printer[] printers); + dictionary PlayStoreState { // Whether the Play Store allowed for the current user. boolean allowed; @@ -138,6 +145,9 @@ // Get state of the Play Store. static void getPlayStoreState(PlayStoreStateCallback callback); + // Get list of available printers + static void getPrinterList(PrinterArrayCallback callback); + // Enable/disable the Play Store. // |enabled|: if set, enable the Play Store. // |callback|: Called when the operation has completed.
diff --git a/chrome/common/extensions/api/developer_private.idl b/chrome/common/extensions/api/developer_private.idl index 80ccc55..eb2e5c4 100644 --- a/chrome/common/extensions/api/developer_private.idl +++ b/chrome/common/extensions/api/developer_private.idl
@@ -491,9 +491,8 @@ callback ItemsInfoCallback = void (ItemInfo[] result); callback ProfileInfoCallback = void (ProfileInfo info); callback GetProjectsInfoCallback = void (ProjectInfo[] result); - callback PathCallback = void (DOMString path); callback PackCallback = void (PackDirectoryResponse response); - callback VoidCallback = void(); + callback StringCallback = void (DOMString string); callback RequestFileSourceCallback = void (RequestFileSourceResponse response); callback LoadErrorCallback = void (optional LoadError error); @@ -517,6 +516,11 @@ static void getExtensionInfo(DOMString id, optional ExtensionInfoCallback callback); + // Returns the size of a particular extension on disk (already formatted). + // |id| : The id of the extension. + // |callback| : Called with the result. + static void getExtensionSize(DOMString id, StringCallback callback); + // Returns information of all the extensions and apps installed. // |includeDisabled| : include disabled items. // |includeTerminated| : include terminated items. @@ -567,7 +571,7 @@ // |directory| : The directory to load the extension from. static void loadDirectory( [instanceOf=DirectoryEntry] object directory, - PathCallback callback); + StringCallback callback); // Open Dialog to browse to an entry. // |selectType| : Select a file or a folder. @@ -576,7 +580,7 @@ // |callback| : called with selected item's path. static void choosePath(SelectType selectType, FileType fileType, - PathCallback callback); + StringCallback callback); // Pack an extension. // |rootPath| : The path of the extension.
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 5a690a0..4c1daa0 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -600,6 +600,9 @@ const char kDisplayProperties[] = "settings.display.properties"; // A dictionary pref that stores the touch associations for the device. const char kDisplayTouchAssociations[] = "settings.display.touch_associations"; +// A list pref that stores the mirror info for each external display. +const char kExternalDisplayMirrorInfo[] = + "settings.display.external_display_mirror_info"; // A dictionary pref that specifies per-display layout/offset information. // Its key is the ID of the display and its value is a dictionary for the
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 65d2302..7a9c1891 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -221,6 +221,7 @@ extern const char kDisplayPowerState[]; extern const char kDisplayProperties[]; extern const char kDisplayTouchAssociations[]; +extern const char kExternalDisplayMirrorInfo[]; extern const char kSecondaryDisplays[]; extern const char kDisplayRotationLock[]; extern const char kNoteTakingAppId[];
diff --git a/chrome/common/printing/BUILD.gn b/chrome/common/printing/BUILD.gn deleted file mode 100644 index 047b22f..0000000 --- a/chrome/common/printing/BUILD.gn +++ /dev/null
@@ -1,17 +0,0 @@ -# Copyright 2017 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//mojo/public/tools/bindings/mojom.gni") - -mojom("interfaces") { - sources = [ - "pdf_to_emf_converter.mojom", - ] - - deps = [ - "//chrome/services/printing/public/interfaces", - "//mojo/common:common_custom_types", - "//ui/gfx/geometry/mojo", - ] -}
diff --git a/chrome/common/printing/OWNERS b/chrome/common/printing/OWNERS deleted file mode 100644 index 065863ca..0000000 --- a/chrome/common/printing/OWNERS +++ /dev/null
@@ -1,2 +0,0 @@ -per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chrome/renderer/extensions/automation_ax_tree_wrapper.cc b/chrome/renderer/extensions/automation_ax_tree_wrapper.cc index f71b3a0f6..41d18a8e 100644 --- a/chrome/renderer/extensions/automation_ax_tree_wrapper.cc +++ b/chrome/renderer/extensions/automation_ax_tree_wrapper.cc
@@ -201,9 +201,16 @@ api::automation::EventType automation_event_type = ToAutomationEvent(params.event_type); + if (automation_event_type == + api::automation::EVENT_TYPE_DOCUMENTSELECTIONCHANGED) + LOG(ERROR) << "AXAX Native DOCUMENT SELECTION CHANGED event"; + // Send some events directly from the event message, if they're not // handled by AXEventGenerator yet. if (!IsEventTypeHandledByAXEventGenerator(automation_event_type)) { + if (automation_event_type == + api::automation::EVENT_TYPE_DOCUMENTSELECTIONCHANGED) + LOG(ERROR) << "AXAX SENDING Native DOCUMENT SELECTION CHANGED event"; owner_->SendAutomationEvent(params, params.id, automation_event_type); } @@ -211,7 +218,11 @@ for (auto targeted_event : *this) { api::automation::EventType event_type = ToAutomationEvent(targeted_event.event); + if (event_type == api::automation::EVENT_TYPE_DOCUMENTSELECTIONCHANGED) + LOG(ERROR) << "AXAX Generated DOCUMENT SELECTION CHANGED event"; if (IsEventTypeHandledByAXEventGenerator(event_type)) { + if (event_type == api::automation::EVENT_TYPE_DOCUMENTSELECTIONCHANGED) + LOG(ERROR) << "AXAX SENDING Generated DOCUMENT SELECTION CHANGED event"; owner_->SendAutomationEvent(params, targeted_event.node->id(), event_type); } @@ -277,54 +288,65 @@ bool AutomationAXTreeWrapper::IsEventTypeHandledByAXEventGenerator( api::automation::EventType event_type) const { switch (event_type) { - case api::automation::EVENT_TYPE_LOADCOMPLETE: - return true; - case api::automation::EVENT_TYPE_NONE: + // Generated by AXEventGenerator. case api::automation::EVENT_TYPE_ACTIVEDESCENDANTCHANGED: - case api::automation::EVENT_TYPE_ALERT: - case api::automation::EVENT_TYPE_ARIAATTRIBUTECHANGED: - case api::automation::EVENT_TYPE_AUTOCORRECTIONOCCURED: - case api::automation::EVENT_TYPE_BLUR: case api::automation::EVENT_TYPE_CHECKEDSTATECHANGED: - case api::automation::EVENT_TYPE_CHILDRENCHANGED: - case api::automation::EVENT_TYPE_CLICKED: - case api::automation::EVENT_TYPE_DOCUMENTSELECTIONCHANGED: case api::automation::EVENT_TYPE_EXPANDEDCHANGED: - case api::automation::EVENT_TYPE_FOCUS: - case api::automation::EVENT_TYPE_HIDE: - case api::automation::EVENT_TYPE_HOVER: - case api::automation::EVENT_TYPE_IMAGEFRAMEUPDATED: case api::automation::EVENT_TYPE_INVALIDSTATUSCHANGED: - case api::automation::EVENT_TYPE_LAYOUTCOMPLETE: - case api::automation::EVENT_TYPE_LIVEREGIONCREATED: case api::automation::EVENT_TYPE_LIVEREGIONCHANGED: - case api::automation::EVENT_TYPE_LOCATIONCHANGED: - case api::automation::EVENT_TYPE_MEDIASTARTEDPLAYING: - case api::automation::EVENT_TYPE_MEDIASTOPPEDPLAYING: - case api::automation::EVENT_TYPE_MENUEND: - case api::automation::EVENT_TYPE_MENULISTITEMSELECTED: + case api::automation::EVENT_TYPE_LIVEREGIONCREATED: + case api::automation::EVENT_TYPE_LOADCOMPLETE: + case api::automation::EVENT_TYPE_SCROLLPOSITIONCHANGED: + case api::automation::EVENT_TYPE_SELECTEDCHILDRENCHANGED: + return true; + + // Not generated by AXEventGenerator and possible candidates + // for removal from the automation API entirely. + case api::automation::EVENT_TYPE_HIDE: + case api::automation::EVENT_TYPE_LAYOUTCOMPLETE: case api::automation::EVENT_TYPE_MENULISTVALUECHANGED: case api::automation::EVENT_TYPE_MENUPOPUPEND: case api::automation::EVENT_TYPE_MENUPOPUPSTART: - case api::automation::EVENT_TYPE_MENUSTART: + case api::automation::EVENT_TYPE_SELECTIONADD: + case api::automation::EVENT_TYPE_SELECTIONREMOVE: + case api::automation::EVENT_TYPE_SHOW: + case api::automation::EVENT_TYPE_TREECHANGED: + return false; + + // These events will never be generated by AXEventGenerator. + // These are all events that can't be inferred from a tree change. + case api::automation::EVENT_TYPE_NONE: + case api::automation::EVENT_TYPE_AUTOCORRECTIONOCCURED: + case api::automation::EVENT_TYPE_CLICKED: + case api::automation::EVENT_TYPE_HOVER: + case api::automation::EVENT_TYPE_MEDIASTARTEDPLAYING: + case api::automation::EVENT_TYPE_MEDIASTOPPEDPLAYING: case api::automation::EVENT_TYPE_MOUSECANCELED: case api::automation::EVENT_TYPE_MOUSEDRAGGED: case api::automation::EVENT_TYPE_MOUSEMOVED: case api::automation::EVENT_TYPE_MOUSEPRESSED: case api::automation::EVENT_TYPE_MOUSERELEASED: + case api::automation::EVENT_TYPE_SCROLLEDTOANCHOR: + return false; + + // These events might need to be migrated to AXEventGenerator. + case api::automation::EVENT_TYPE_ALERT: + case api::automation::EVENT_TYPE_ARIAATTRIBUTECHANGED: + case api::automation::EVENT_TYPE_BLUR: + case api::automation::EVENT_TYPE_CHILDRENCHANGED: + case api::automation::EVENT_TYPE_DOCUMENTSELECTIONCHANGED: + case api::automation::EVENT_TYPE_FOCUS: + case api::automation::EVENT_TYPE_IMAGEFRAMEUPDATED: + case api::automation::EVENT_TYPE_LOCATIONCHANGED: + case api::automation::EVENT_TYPE_MENUEND: + case api::automation::EVENT_TYPE_MENULISTITEMSELECTED: + case api::automation::EVENT_TYPE_MENUSTART: case api::automation::EVENT_TYPE_ROWCOLLAPSED: case api::automation::EVENT_TYPE_ROWCOUNTCHANGED: case api::automation::EVENT_TYPE_ROWEXPANDED: - case api::automation::EVENT_TYPE_SCROLLPOSITIONCHANGED: - case api::automation::EVENT_TYPE_SCROLLEDTOANCHOR: - case api::automation::EVENT_TYPE_SELECTEDCHILDRENCHANGED: case api::automation::EVENT_TYPE_SELECTION: - case api::automation::EVENT_TYPE_SELECTIONADD: - case api::automation::EVENT_TYPE_SELECTIONREMOVE: - case api::automation::EVENT_TYPE_SHOW: case api::automation::EVENT_TYPE_TEXTCHANGED: case api::automation::EVENT_TYPE_TEXTSELECTIONCHANGED: - case api::automation::EVENT_TYPE_TREECHANGED: case api::automation::EVENT_TYPE_VALUECHANGED: return false; }
diff --git a/chrome/services/printing/BUILD.gn b/chrome/services/printing/BUILD.gn index b0d17f2..10a1951 100644 --- a/chrome/services/printing/BUILD.gn +++ b/chrome/services/printing/BUILD.gn
@@ -22,6 +22,17 @@ "//chrome/services/printing/public/interfaces", "//services/service_manager/public/cpp", ] + + if (is_win) { + sources += [ + "pdf_to_emf_converter.cc", + "pdf_to_emf_converter.h", + "pdf_to_emf_converter_factory.cc", + "pdf_to_emf_converter_factory.h", + ] + + deps += [ "//skia" ] + } } service_manifest("manifest") {
diff --git a/chrome/services/printing/DEPS b/chrome/services/printing/DEPS index e54e31e..ad8e5a9 100644 --- a/chrome/services/printing/DEPS +++ b/chrome/services/printing/DEPS
@@ -1,3 +1,3 @@ -include_rules = [ - "+chrome/utility/cloud_print", -] +include_rules = [ + "+chrome/utility/cloud_print", +]
diff --git a/chrome/services/printing/manifest.json b/chrome/services/printing/manifest.json index 239cc3dd..27b3b9c 100644 --- a/chrome/services/printing/manifest.json +++ b/chrome/services/printing/manifest.json
@@ -1,10 +1,13 @@ { "name": "chrome_printing", "display_name": "Printing", + "sandbox_type": "utility", "interface_provider_specs": { "service_manager:connector": { "provides": { - "converter": [ "printing::mojom::PdfToPwgRasterConverter" ] + "converter": [ + "printing::mojom::PdfToEmfConverterFactory", + "printing::mojom::PdfToPwgRasterConverter" ] }, "requires": { "service_manager": [ "service_manager:all_users" ]
diff --git a/chrome/utility/printing/pdf_to_emf_converter_impl.cc b/chrome/services/printing/pdf_to_emf_converter.cc similarity index 88% rename from chrome/utility/printing/pdf_to_emf_converter_impl.cc rename to chrome/services/printing/pdf_to_emf_converter.cc index 359c33d..e914ea9 100644 --- a/chrome/utility/printing/pdf_to_emf_converter_impl.cc +++ b/chrome/services/printing/pdf_to_emf_converter.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/utility/printing/pdf_to_emf_converter_impl.h" +#include "chrome/services/printing/pdf_to_emf_converter.h" #include <algorithm> @@ -61,7 +61,7 @@ } // namespace -PdfToEmfConverterImpl::PdfToEmfConverterImpl( +PdfToEmfConverter::PdfToEmfConverter( mojo::ScopedHandle pdf_file_in, const printing::PdfRenderSettings& pdf_render_settings, mojom::PdfToEmfConverterClientPtr client) @@ -90,15 +90,15 @@ base::PlatformFile pdf_file; if (mojo::UnwrapPlatformFile(std::move(pdf_file_in), &pdf_file) != MOJO_RESULT_OK) { - LOG(ERROR) << "Invalid PDF file passed to PdfToEmfConverterImpl"; + LOG(ERROR) << "Invalid PDF file passed to PdfToEmfConverter."; return; } LoadPdf(base::File(pdf_file)); } -PdfToEmfConverterImpl::~PdfToEmfConverterImpl() = default; +PdfToEmfConverter::~PdfToEmfConverter() = default; -void PdfToEmfConverterImpl::LoadPdf(base::File pdf_file) { +void PdfToEmfConverter::LoadPdf(base::File pdf_file) { int64_t length64 = pdf_file.GetLength(); if (length64 <= 0 || length64 > std::numeric_limits<int>::max()) return; @@ -114,10 +114,10 @@ total_page_count_ = page_count; } -bool PdfToEmfConverterImpl::RenderPdfPageToMetafile(int page_number, - base::File output_file, - float* scale_factor, - bool postscript) { +bool PdfToEmfConverter::RenderPdfPageToMetafile(int page_number, + base::File output_file, + float* scale_factor, + bool postscript) { Emf metafile; metafile.Init(); @@ -160,9 +160,9 @@ return metafile.SaveTo(&output_file); } -void PdfToEmfConverterImpl::ConvertPage(uint32_t page_number, - mojo::ScopedHandle emf_file_out, - ConvertPageCallback callback) { +void PdfToEmfConverter::ConvertPage(uint32_t page_number, + mojo::ScopedHandle emf_file_out, + ConvertPageCallback callback) { if (page_number >= total_page_count_) { std::move(callback).Run(/*success=*/false, /*scale_factor=*/0.0); return;
diff --git a/chrome/utility/printing/pdf_to_emf_converter_impl.h b/chrome/services/printing/pdf_to_emf_converter.h similarity index 61% rename from chrome/utility/printing/pdf_to_emf_converter_impl.h rename to chrome/services/printing/pdf_to_emf_converter.h index 56644fa..e2c6ed4 100644 --- a/chrome/utility/printing/pdf_to_emf_converter_impl.h +++ b/chrome/services/printing/pdf_to_emf_converter.h
@@ -2,24 +2,24 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_UTILITY_PRINTING_PDF_TO_EMF_CONVERTER_IMPL_H_ -#define CHROME_UTILITY_PRINTING_PDF_TO_EMF_CONVERTER_IMPL_H_ +#ifndef CHROME_SERVICES_PRINTING_PDF_TO_EMF_CONVERTER_H_ +#define CHROME_SERVICES_PRINTING_PDF_TO_EMF_CONVERTER_H_ #include <vector> #include "base/files/file.h" #include "base/macros.h" -#include "chrome/common/printing/pdf_to_emf_converter.mojom.h" +#include "chrome/services/printing/public/interfaces/pdf_to_emf_converter.mojom.h" #include "printing/pdf_render_settings.h" namespace printing { -class PdfToEmfConverterImpl : public mojom::PdfToEmfConverter { +class PdfToEmfConverter : public mojom::PdfToEmfConverter { public: - PdfToEmfConverterImpl(mojo::ScopedHandle pdf_file_in, - const PdfRenderSettings& render_settings, - mojom::PdfToEmfConverterClientPtr client); - ~PdfToEmfConverterImpl() override; + PdfToEmfConverter(mojo::ScopedHandle pdf_file_in, + const PdfRenderSettings& render_settings, + mojom::PdfToEmfConverterClientPtr client); + ~PdfToEmfConverter() override; int total_page_count() const { return total_page_count_; } @@ -39,9 +39,9 @@ PdfRenderSettings pdf_render_settings_; std::vector<char> pdf_data_; - DISALLOW_COPY_AND_ASSIGN(PdfToEmfConverterImpl); + DISALLOW_COPY_AND_ASSIGN(PdfToEmfConverter); }; } // namespace printing -#endif // CHROME_UTILITY_PRINTING_PDF_TO_EMF_CONVERTER_IMPL_H_ +#endif // CHROME_SERVICES_PRINTING_PDF_TO_EMF_CONVERTER_H_
diff --git a/chrome/services/printing/pdf_to_emf_converter_factory.cc b/chrome/services/printing/pdf_to_emf_converter_factory.cc new file mode 100644 index 0000000..5e6c0e95 --- /dev/null +++ b/chrome/services/printing/pdf_to_emf_converter_factory.cc
@@ -0,0 +1,34 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/services/printing/pdf_to_emf_converter_factory.h" + +#include "chrome/services/printing/pdf_to_emf_converter.h" +#include "mojo/public/cpp/bindings/strong_binding.h" +#include "mojo/public/cpp/system/platform_handle.h" + +namespace printing { + +PdfToEmfConverterFactory::PdfToEmfConverterFactory( + std::unique_ptr<service_manager::ServiceContextRef> service_ref) + : service_ref_(std::move(service_ref)) {} + +PdfToEmfConverterFactory::~PdfToEmfConverterFactory() = default; + +void PdfToEmfConverterFactory::CreateConverter( + mojo::ScopedHandle pdf_file_in, + const PdfRenderSettings& render_settings, + mojom::PdfToEmfConverterClientPtr client, + CreateConverterCallback callback) { + auto converter = std::make_unique<PdfToEmfConverter>( + std::move(pdf_file_in), render_settings, std::move(client)); + uint32_t page_count = converter->total_page_count(); + mojom::PdfToEmfConverterPtr converter_ptr; + mojo::MakeStrongBinding(std::move(converter), + mojo::MakeRequest(&converter_ptr)); + + std::move(callback).Run(std::move(converter_ptr), page_count); +} + +} // namespace printing
diff --git a/chrome/services/printing/pdf_to_emf_converter_factory.h b/chrome/services/printing/pdf_to_emf_converter_factory.h new file mode 100644 index 0000000..10a658c --- /dev/null +++ b/chrome/services/printing/pdf_to_emf_converter_factory.h
@@ -0,0 +1,34 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_SERVICES_PRINTING_PDF_TO_EMF_CONVERTER_FACTORY_H_ +#define CHROME_SERVICES_PRINTING_PDF_TO_EMF_CONVERTER_FACTORY_H_ + +#include "base/macros.h" +#include "chrome/services/printing/public/interfaces/pdf_to_emf_converter.mojom.h" +#include "services/service_manager/public/cpp/service_context_ref.h" + +namespace printing { + +class PdfToEmfConverterFactory : public mojom::PdfToEmfConverterFactory { + public: + explicit PdfToEmfConverterFactory( + std::unique_ptr<service_manager::ServiceContextRef> service_ref); + ~PdfToEmfConverterFactory() override; + + private: + // mojom::PdfToEmfConverterFactory implementation. + void CreateConverter(mojo::ScopedHandle pdf_file_in, + const PdfRenderSettings& render_settings, + mojom::PdfToEmfConverterClientPtr client, + CreateConverterCallback callback) override; + + const std::unique_ptr<service_manager::ServiceContextRef> service_ref_; + + DISALLOW_COPY_AND_ASSIGN(PdfToEmfConverterFactory); +}; + +} // namespace printing + +#endif // CHROME_SERVICES_PRINTING_PDF_TO_EMF_CONVERTER_FACTORY_H_
diff --git a/chrome/services/printing/pdf_to_pwg_raster_converter.cc b/chrome/services/printing/pdf_to_pwg_raster_converter.cc index c76809f..693ebb7 100644 --- a/chrome/services/printing/pdf_to_pwg_raster_converter.cc +++ b/chrome/services/printing/pdf_to_pwg_raster_converter.cc
@@ -4,6 +4,10 @@ #include "chrome/services/printing/pdf_to_pwg_raster_converter.h" +#include <limits> +#include <string> +#include <utility> + #include "chrome/utility/cloud_print/bitmap_image.h" #include "chrome/utility/cloud_print/pwg_encoder.h" #include "mojo/public/cpp/bindings/strong_binding.h" @@ -59,6 +63,9 @@ cloud_print::PwgHeaderInfo header_info; header_info.dpi = gfx::Size(settings.dpi, settings.dpi); header_info.total_pages = total_page_count; + header_info.color_space = bitmap_settings.use_color + ? cloud_print::PwgHeaderInfo::SRGB + : cloud_print::PwgHeaderInfo::SGRAY; // Transform odd pages. if (page_number % 2) { @@ -97,13 +104,13 @@ } // namespace -PdfToPwgRasterConverterImpl::PdfToPwgRasterConverterImpl( +PdfToPwgRasterConverter::PdfToPwgRasterConverter( std::unique_ptr<service_manager::ServiceContextRef> service_ref) : service_ref_(std::move(service_ref)) {} -PdfToPwgRasterConverterImpl::~PdfToPwgRasterConverterImpl() {} +PdfToPwgRasterConverter::~PdfToPwgRasterConverter() {} -void PdfToPwgRasterConverterImpl::Convert( +void PdfToPwgRasterConverter::Convert( mojo::ScopedHandle pdf_file_in, const PdfRenderSettings& pdf_settings, const PwgRasterSettings& pwg_raster_settings, @@ -112,7 +119,7 @@ base::PlatformFile pdf_file; if (mojo::UnwrapPlatformFile(std::move(pdf_file_in), &pdf_file) != MOJO_RESULT_OK) { - LOG(ERROR) << "Invalid PDF file passed to PdfToPwgRasterConverterImpl"; + LOG(ERROR) << "Invalid PDF file passed to PdfToPwgRasterConverter."; std::move(callback).Run(false); return; } @@ -120,8 +127,7 @@ base::PlatformFile pwg_raster_file; if (mojo::UnwrapPlatformFile(std::move(pwg_raster_file_out), &pwg_raster_file) != MOJO_RESULT_OK) { - LOG(ERROR) - << "Invalid PWGRaster file passed to PdfToPwgRasterConverterImpl"; + LOG(ERROR) << "Invalid PWGRaster file passed to PdfToPwgRasterConverter."; std::move(callback).Run(false); return; }
diff --git a/chrome/services/printing/pdf_to_pwg_raster_converter.h b/chrome/services/printing/pdf_to_pwg_raster_converter.h index 6d524f8..6d5b6b5 100644 --- a/chrome/services/printing/pdf_to_pwg_raster_converter.h +++ b/chrome/services/printing/pdf_to_pwg_raster_converter.h
@@ -16,12 +16,12 @@ struct PdfRenderSettings; -class PdfToPwgRasterConverterImpl +class PdfToPwgRasterConverter : public printing::mojom::PdfToPwgRasterConverter { public: - explicit PdfToPwgRasterConverterImpl( + explicit PdfToPwgRasterConverter( std::unique_ptr<service_manager::ServiceContextRef> service_ref); - ~PdfToPwgRasterConverterImpl() override; + ~PdfToPwgRasterConverter() override; private: // printing::mojom::PdfToPwgRasterConverter @@ -33,7 +33,7 @@ const std::unique_ptr<service_manager::ServiceContextRef> service_ref_; - DISALLOW_COPY_AND_ASSIGN(PdfToPwgRasterConverterImpl); + DISALLOW_COPY_AND_ASSIGN(PdfToPwgRasterConverter); }; } // namespace printing
diff --git a/chrome/services/printing/printing_service.cc b/chrome/services/printing/printing_service.cc index 434f1627..59def54 100644 --- a/chrome/services/printing/printing_service.cc +++ b/chrome/services/printing/printing_service.cc
@@ -8,17 +8,31 @@ #include "chrome/services/printing/pdf_to_pwg_raster_converter.h" #include "mojo/public/cpp/bindings/strong_binding.h" +#if defined(OS_WIN) +#include "chrome/services/printing/pdf_to_emf_converter.h" +#include "chrome/services/printing/pdf_to_emf_converter_factory.h" +#endif + namespace printing { namespace { +#if defined(OS_WIN) +void OnPdfToEmfConverterFactoryRequest( + service_manager::ServiceContextRefFactory* ref_factory, + printing::mojom::PdfToEmfConverterFactoryRequest request) { + mojo::MakeStrongBinding(std::make_unique<printing::PdfToEmfConverterFactory>( + ref_factory->CreateRef()), + std::move(request)); +} +#endif + void OnPdfToPwgRasterConverterRequest( service_manager::ServiceContextRefFactory* ref_factory, printing::mojom::PdfToPwgRasterConverterRequest request) { - mojo::MakeStrongBinding( - std::make_unique<printing::PdfToPwgRasterConverterImpl>( - ref_factory->CreateRef()), - std::move(request)); + mojo::MakeStrongBinding(std::make_unique<printing::PdfToPwgRasterConverter>( + ref_factory->CreateRef()), + std::move(request)); } } // namespace @@ -35,6 +49,10 @@ ref_factory_ = std::make_unique<service_manager::ServiceContextRefFactory>( base::Bind(&service_manager::ServiceContext::RequestQuit, base::Unretained(context()))); +#if defined(OS_WIN) + registry_.AddInterface( + base::Bind(&OnPdfToEmfConverterFactoryRequest, ref_factory_.get())); +#endif registry_.AddInterface( base::Bind(&OnPdfToPwgRasterConverterRequest, ref_factory_.get())); }
diff --git a/chrome/services/printing/public/interfaces/BUILD.gn b/chrome/services/printing/public/interfaces/BUILD.gn index 1596bd62..aaf9052 100644 --- a/chrome/services/printing/public/interfaces/BUILD.gn +++ b/chrome/services/printing/public/interfaces/BUILD.gn
@@ -11,6 +11,10 @@ "pdf_to_pwg_raster_converter.mojom", ] + if (is_win) { + sources += [ "pdf_to_emf_converter.mojom" ] + } + deps = [ "//mojo/common:common_custom_types", "//ui/gfx/geometry/mojo",
diff --git a/chrome/services/printing/public/interfaces/OWNERS b/chrome/services/printing/public/interfaces/OWNERS index 9526caa..2c44a46 100644 --- a/chrome/services/printing/public/interfaces/OWNERS +++ b/chrome/services/printing/public/interfaces/OWNERS
@@ -1,6 +1,6 @@ -per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS -per-file *_struct_traits*.*=set noparent -per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS -per-file *.typemap=set noparent -per-file *.typemap=file://ipc/SECURITY_OWNERS +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS +per-file *_struct_traits*.*=set noparent +per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS +per-file *.typemap=set noparent +per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/chrome/common/printing/pdf_to_emf_converter.mojom b/chrome/services/printing/public/interfaces/pdf_to_emf_converter.mojom similarity index 100% rename from chrome/common/printing/pdf_to_emf_converter.mojom rename to chrome/services/printing/public/interfaces/pdf_to_emf_converter.mojom
diff --git a/chrome/services/printing/public/interfaces/pdf_to_pwg_raster_converter.mojom b/chrome/services/printing/public/interfaces/pdf_to_pwg_raster_converter.mojom index 760f812..d0f5f44f 100644 --- a/chrome/services/printing/public/interfaces/pdf_to_pwg_raster_converter.mojom +++ b/chrome/services/printing/public/interfaces/pdf_to_pwg_raster_converter.mojom
@@ -22,6 +22,9 @@ // Rasterize pages in reverse order. bool reverse_page_order; + + // Rasterize pages in color. + bool use_color; }; interface PdfToPwgRasterConverter {
diff --git a/chrome/services/printing/public/interfaces/pdf_to_pwg_raster_converter_struct_traits.cc b/chrome/services/printing/public/interfaces/pdf_to_pwg_raster_converter_struct_traits.cc index c9eac84..4f34624 100644 --- a/chrome/services/printing/public/interfaces/pdf_to_pwg_raster_converter_struct_traits.cc +++ b/chrome/services/printing/public/interfaces/pdf_to_pwg_raster_converter_struct_traits.cc
@@ -13,6 +13,7 @@ printing::PwgRasterSettings* out) { out->rotate_all_pages = data.rotate_all_pages(); out->reverse_page_order = data.reverse_page_order(); + out->use_color = data.use_color(); return data.ReadOddPageTransform(&out->odd_page_transform); }
diff --git a/chrome/services/printing/public/interfaces/pdf_to_pwg_raster_converter_struct_traits.h b/chrome/services/printing/public/interfaces/pdf_to_pwg_raster_converter_struct_traits.h index 213f077..f5dfbf4 100644 --- a/chrome/services/printing/public/interfaces/pdf_to_pwg_raster_converter_struct_traits.h +++ b/chrome/services/printing/public/interfaces/pdf_to_pwg_raster_converter_struct_traits.h
@@ -69,6 +69,9 @@ static bool reverse_page_order(const printing::PwgRasterSettings& settings) { return settings.reverse_page_order; } + static bool use_color(const printing::PwgRasterSettings& settings) { + return settings.use_color; + } static printing::PwgRasterTransformType odd_page_transform( const printing::PwgRasterSettings& settings) { return settings.odd_page_transform;
diff --git a/chrome/services/wifi_util_win/OWNERS b/chrome/services/wifi_util_win/OWNERS index 6ea179f..59c3141 100644 --- a/chrome/services/wifi_util_win/OWNERS +++ b/chrome/services/wifi_util_win/OWNERS
@@ -1,4 +1,4 @@ -noel@chromium.org - -per-file manifest.json=set noparent -per-file manifest.json=file://ipc/SECURITY_OWNERS +noel@chromium.org + +per-file manifest.json=set noparent +per-file manifest.json=file://ipc/SECURITY_OWNERS
diff --git a/chrome/services/wifi_util_win/public/interfaces/OWNERS b/chrome/services/wifi_util_win/public/interfaces/OWNERS index 065863ca..08850f4 100644 --- a/chrome/services/wifi_util_win/public/interfaces/OWNERS +++ b/chrome/services/wifi_util_win/public/interfaces/OWNERS
@@ -1,2 +1,2 @@ -per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 004f3f9..1bf7cb09a1 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -287,10 +287,10 @@ "//content/test/gpu/", "//content/test/data/gpu/", - # For the Maps WPR archive SHA. Include the entire directory to - # avoid having to update this BUILD.gn file if the WPR is - # re-recorded. - "//tools/perf/page_sets/data/", + # For the Maps performance test. Include the entire directory to + # avoid having to update this BUILD.gn file if more files are + # added in the future. + "//tools/perf/page_sets/maps_perf_test/", # For depth_capture "//content/test/data/media/depth_stream_test_utilities.js", @@ -535,6 +535,7 @@ "../browser/media/media_browsertest.h", "../browser/media/media_engagement_autoplay_browsertest.cc", "../browser/media/media_engagement_browsertest.cc", + "../browser/media/router/independent_otr_profile_manager_browsertest.cc", "../browser/media/test_license_server.cc", "../browser/media/test_license_server.h", "../browser/media/test_license_server_config.h", @@ -1389,6 +1390,7 @@ # TODO(tapted): Move these to chrome_browser_tests_views_sources when the # the corresponding files are moved in chrome_browser_ui.gypi (i.e. out of # chrome_browser_ui_views_non_mac_sources). http://crbug.com/404979. + "../browser/ui/media_router/presentation_receiver_window_controller_browsertest.cc", "../browser/ui/views/autofill/autofill_popup_base_view_browsertest.cc", "../browser/ui/views/autofill/autofill_popup_view_views_browsertest.cc", "../browser/ui/views/autofill/password_generation_popup_view_tester_views.cc", @@ -2181,7 +2183,7 @@ "../browser/budget_service/budget_manager_unittest.cc", "../browser/chrome_content_browser_client_unittest.cc", "../browser/chrome_process_singleton_win_unittest.cc", - "../browser/command_updater_unittest.cc", + "../browser/command_updater_impl_unittest.cc", "../browser/component_updater/chrome_component_updater_configurator_unittest.cc", "../browser/component_updater/component_installer_errors_unittest.cc", "../browser/component_updater/optimization_hints_component_installer_unittest.cc", @@ -2783,6 +2785,7 @@ "../browser/resource_coordinator/tab_lifecycle_unit_source_unittest.cc", "../browser/resource_coordinator/tab_lifecycle_unit_unittest.cc", "../browser/resource_coordinator/tab_manager_delegate_chromeos_unittest.cc", + "../browser/resource_coordinator/tab_manager_features_unittest.cc", "../browser/resource_coordinator/tab_manager_stats_collector_unittest.cc", "../browser/resource_coordinator/tab_manager_unittest.cc", "../browser/resource_coordinator/tab_manager_web_contents_data_unittest.cc",
diff --git a/chrome/test/base/testing_browser_process.cc b/chrome/test/base/testing_browser_process.cc index b36b8e7..386aeff9 100644 --- a/chrome/test/base/testing_browser_process.cc +++ b/chrome/test/base/testing_browser_process.cc
@@ -237,9 +237,11 @@ return nullptr; } -GpuProfileCache* TestingBrowserProcess::gpu_profile_cache() { +#if defined(OS_ANDROID) +GpuDriverInfoManager* TestingBrowserProcess::gpu_driver_info_manager() { return nullptr; } +#endif GpuModeManager* TestingBrowserProcess::gpu_mode_manager() { return nullptr;
diff --git a/chrome/test/base/testing_browser_process.h b/chrome/test/base/testing_browser_process.h index c87a265..850d330 100644 --- a/chrome/test/base/testing_browser_process.h +++ b/chrome/test/base/testing_browser_process.h
@@ -77,7 +77,9 @@ policy::BrowserPolicyConnector* browser_policy_connector() override; policy::PolicyService* policy_service() override; IconManager* icon_manager() override; - GpuProfileCache* gpu_profile_cache() override; +#if defined(OS_ANDROID) + GpuDriverInfoManager* gpu_driver_info_manager() override; +#endif GpuModeManager* gpu_mode_manager() override; BackgroundModeManager* background_mode_manager() override; void set_background_mode_manager_for_test(
diff --git a/chrome/test/data/extensions/api_test/automation/tests/desktop/hit_test.js b/chrome/test/data/extensions/api_test/automation/tests/desktop/hit_test.js index b29b09d7e..fb17ea4 100644 --- a/chrome/test/data/extensions/api_test/automation/tests/desktop/hit_test.js +++ b/chrome/test/data/extensions/api_test/automation/tests/desktop/hit_test.js
@@ -19,7 +19,7 @@ role: 'button' } }); if (button) { didHitTest = true; - button.addEventListener(EventType.ALERT, function() { + button.addEventListener(EventType.CLICKED, function() { chrome.test.succeed(); }, true); // Click just barely on the second button, very close @@ -27,7 +27,7 @@ // coordinate properly. var cx = button.location.left + 10; var cy = button.location.top + 10; - desktop.hitTest(cx, cy, EventType.ALERT); + desktop.hitTest(cx, cy, EventType.CLICKED); } } }, false);
diff --git a/chrome/test/data/extensions/api_test/automation/tests/tabs/hit_test.js b/chrome/test/data/extensions/api_test/automation/tests/tabs/hit_test.js index 0d40877..071c0873 100644 --- a/chrome/test/data/extensions/api_test/automation/tests/tabs/hit_test.js +++ b/chrome/test/data/extensions/api_test/automation/tests/tabs/hit_test.js
@@ -17,10 +17,10 @@ button1.addEventListener(EventType.HOVER, function() { x = button2.location.left + button2.location.width / 2; y = button2.location.top + button2.location.height / 2; - button2.addEventListener(EventType.ALERT, function() { + button2.addEventListener(EventType.CLICKED, function() { chrome.test.succeed(); }, true); - webArea.hitTest(x, y, EventType.ALERT); + webArea.hitTest(x, y, EventType.CLICKED); }, true); webArea.hitTest(x, y, EventType.HOVER); }
diff --git a/chrome/test/data/extensions/api_test/autotest_private/test.js b/chrome/test/data/extensions/api_test/autotest_private/test.js index 158197e..d0f72c3f 100644 --- a/chrome/test/data/extensions/api_test/autotest_private/test.js +++ b/chrome/test/data/extensions/api_test/autotest_private/test.js
@@ -129,5 +129,10 @@ chrome.test.assertTrue(chrome.runtime.lastError != undefined); chrome.test.succeed(); }); + }, + function getPrinterList() { + chrome.autotestPrivate.getPrinterList(function(){ + chrome.test.succeed(); + }); } ]);
diff --git a/chrome/test/data/media/router/presentation_receiver.html b/chrome/test/data/media/router/presentation_receiver.html new file mode 100644 index 0000000..b9692be --- /dev/null +++ b/chrome/test/data/media/router/presentation_receiver.html
@@ -0,0 +1,32 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>Media Router Integration Test - Receiver Page</title> + <script> + const addConnection = connection => { + connection.onconnect = () => { + connection.onmessage = event => { + if (event.data == 'close') { + connection.close(); + } else { + connection.send('Pong: ' + event.data); + } + }; + connection.send('ready'); + }; + }; + + navigator.presentation.receiver.connectionList + .then(list => { + list.onconnectionavailable = evt => { + addConnection(evt.connection); + }; + list.connections.map(connection => { + addConnection(connection); + }); + }); + </script> + </head> + <body> + </body> +</html>
diff --git a/chrome/test/data/printing/pdf_to_pwg_raster_mono_test.pwg b/chrome/test/data/printing/pdf_to_pwg_raster_mono_test.pwg new file mode 100644 index 0000000..5f71a0a --- /dev/null +++ b/chrome/test/data/printing/pdf_to_pwg_raster_mono_test.pwg Binary files differ
diff --git a/chrome/test/data/printing/pdf_to_pwg_raster_mono_test_32.pwg b/chrome/test/data/printing/pdf_to_pwg_raster_mono_test_32.pwg new file mode 100644 index 0000000..f6d99346 --- /dev/null +++ b/chrome/test/data/printing/pdf_to_pwg_raster_mono_test_32.pwg Binary files differ
diff --git a/chrome/test/data/webui/extensions/extension_detail_view_test.js b/chrome/test/data/webui/extensions/extension_detail_view_test.js index 79ef69d..f848edde 100644 --- a/chrome/test/data/webui/extensions/extension_detail_view_test.js +++ b/chrome/test/data/webui/extensions/extension_detail_view_test.js
@@ -127,6 +127,14 @@ Polymer.dom.flush(); expectTrue(testIsVisible('#id-section')); expectTrue(testIsVisible('#inspectable-views')); + + // Ensure that the "Extension options" button is disabled when the item + // itself is disabled. + var extensionOptions = item.$$('#extensions-options'); + assertFalse(extensionOptions.disabled); + item.set('data.state', chrome.developerPrivate.ExtensionState.DISABLED); + Polymer.dom.flush(); + assertTrue(extensionOptions.disabled); }); test(assert(TestNames.LayoutSource), function() {
diff --git a/chrome/test/data/webui/extensions/extension_pack_dialog_test.js b/chrome/test/data/webui/extensions/extension_pack_dialog_test.js index 5ea0105f..b2da000 100644 --- a/chrome/test/data/webui/extensions/extension_pack_dialog_test.js +++ b/chrome/test/data/webui/extensions/extension_pack_dialog_test.js
@@ -105,6 +105,8 @@ test(assert(TestNames.PackSuccess), function() { var dialogElement = packDialog.$$('dialog'); + var packDialogAlert; + var alertElement; packDialog.show(); expectTrue(extension_test_util.isElementVisible(dialogElement)); @@ -125,6 +127,18 @@ return PolymerTest.flushTasks(); }) .then(() => { + packDialogAlert = packDialog.$$('extensions-pack-dialog-alert'); + alertElement = packDialogAlert.$.dialog; + expectTrue(extension_test_util.isElementVisible(alertElement)); + expectTrue(extension_test_util.isElementVisible(dialogElement)); + expectTrue(!!packDialogAlert.$$('.action-button')); + + // After 'ok', both dialogs should be closed. + MockInteractions.tap(packDialogAlert.$$('.action-button')); + return PolymerTest.flushTasks(); + }) + .then(() => { + expectFalse(extension_test_util.isElementVisible(alertElement)); expectFalse(extension_test_util.isElementVisible(dialogElement)); }); }); @@ -155,11 +169,11 @@ alertElement = packDialogAlert.$.dialog; expectTrue(extension_test_util.isElementVisible(alertElement)); expectTrue(extension_test_util.isElementVisible(dialogElement)); - expectFalse(packDialogAlert.$$('.cancel-button').hidden); - expectTrue(packDialogAlert.$$('.action-button').hidden); + expectTrue(!!packDialogAlert.$$('.action-button')); // After cancel, original dialog is still open and values unchanged. - MockInteractions.tap(packDialogAlert.$$('.cancel-button')); + MockInteractions.tap(packDialogAlert.$$('.action-button')); + Polymer.dom.flush(); expectFalse(extension_test_util.isElementVisible(alertElement)); expectTrue(extension_test_util.isElementVisible(dialogElement)); expectEquals(kRootPath, packDialog.$$('#root-dir').value);
diff --git a/chrome/test/data/webui/extensions/extension_test_util.js b/chrome/test/data/webui/extensions/extension_test_util.js index 4d6235651e..3c608dd 100644 --- a/chrome/test/data/webui/extensions/extension_test_util.js +++ b/chrome/test/data/webui/extensions/extension_test_util.js
@@ -131,6 +131,11 @@ /** @override */ showInFolder: function(id) {}, + + /** @override */ + getExtensionSize: function(id) { + return Promise.resolve('10 MB'); + }, }; /**
diff --git a/chrome/test/data/webui/extensions/test_service.js b/chrome/test/data/webui/extensions/test_service.js index 621d9dd..62de4cd3f 100644 --- a/chrome/test/data/webui/extensions/test_service.js +++ b/chrome/test/data/webui/extensions/test_service.js
@@ -8,6 +8,7 @@ constructor() { super([ 'getExtensionsInfo', + 'getExtensionSize', 'getProfileConfiguration', 'loadUnpacked', 'retryLoadUnpacked', @@ -65,6 +66,12 @@ } /** @override */ + getExtensionSize() { + this.methodCalled('getExtensionSize'); + return Promise.resolve('20 MB'); + } + + /** @override */ setShortcutHandlingSuspended(enable) { this.methodCalled('setShortcutHandlingSuspended', enable); }
diff --git a/chrome/test/data/webui/print_preview/native_layer_stub.js b/chrome/test/data/webui/print_preview/native_layer_stub.js index 72044e77..16451822 100644 --- a/chrome/test/data/webui/print_preview/native_layer_stub.js +++ b/chrome/test/data/webui/print_preview/native_layer_stub.js
@@ -9,6 +9,7 @@ class NativeLayerStub extends TestBrowserProxy { constructor() { super([ + 'dialogClose', 'getInitialSettings', 'getPrinters', 'getPreview', @@ -59,6 +60,11 @@ } /** @override */ + dialogClose(isCancel) { + this.methodCalled('dialogClose', isCancel); + } + + /** @override */ getInitialSettings() { this.methodCalled('getInitialSettings'); return Promise.resolve(this.initialSettings_);
diff --git a/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js b/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js index 97a0902..75bc7d9c 100644 --- a/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js +++ b/chrome/test/data/webui/print_preview/new_print_preview_ui_browsertest.js
@@ -50,6 +50,7 @@ /** @override */ get extraLibraries() { return super.extraLibraries.concat([ + 'print_preview_test_utils.js', 'settings_section_test.js', ]); } @@ -103,7 +104,7 @@ return super.extraLibraries.concat([ '../test_browser_proxy.js', 'native_layer_stub.js', - 'print_preview_tests.js', + 'print_preview_test_utils.js', 'restore_state_test.js', ]); }
diff --git a/chrome/test/data/webui/print_preview/print_preview_test_utils.js b/chrome/test/data/webui/print_preview/print_preview_test_utils.js new file mode 100644 index 0000000..4f7c8c1 --- /dev/null +++ b/chrome/test/data/webui/print_preview/print_preview_test_utils.js
@@ -0,0 +1,74 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +cr.define('print_preview_test_utils', function() { + + /** + * @param {string} printerId + * @param {string=} opt_printerName Defaults to an empty string. + * @return {!print_preview.PrinterCapabilitiesResponse} + */ + function getCddTemplate(printerId, opt_printerName) { + return { + printer: { + deviceName: printerId, + printerName: opt_printerName || '', + }, + capabilities: { + version: '1.0', + printer: { + supported_content_type: [{content_type: 'application/pdf'}], + collate: {default: true}, + copies: {default: 1, max: 1000}, + color: { + option: [ + {type: 'STANDARD_COLOR', is_default: true}, + {type: 'STANDARD_MONOCHROME'} + ] + }, + dpi: { + option: [ + {horizontal_dpi: 200, vertical_dpi: 200, is_default: true}, + {horizontal_dpi: 100, vertical_dpi: 100}, + ] + }, + duplex: { + option: [ + {type: 'NO_DUPLEX', is_default: true}, + {type: 'LONG_EDGE'}, + {type: 'SHORT_EDGE'} + ] + }, + page_orientation: { + option: [ + {type: 'PORTRAIT', is_default: true}, + {type: 'LANDSCAPE'}, + {type: 'AUTO'} + ] + }, + media_size: { + option: [ + { name: 'NA_LETTER', + width_microns: 215900, + height_microns: 279400, + is_default: true, + custom_display_name: "Letter", + }, + { + name: 'CUSTOM_SQUARE', + width_microns: 215900, + height_microns: 215900, + custom_display_name: "CUSTOM_SQUARE", + } + ] + } + } + } + }; + } + + return { + getCddTemplate: getCddTemplate, + }; +});
diff --git a/chrome/test/data/webui/print_preview/print_preview_tests.js b/chrome/test/data/webui/print_preview/print_preview_tests.js index a828b27..93343b5 100644 --- a/chrome/test/data/webui/print_preview/print_preview_tests.js +++ b/chrome/test/data/webui/print_preview/print_preview_tests.js
@@ -59,7 +59,8 @@ function setupSettingsAndDestinationsWithCapabilities(opt_device) { nativeLayer.setInitialSettings(initialSettings); nativeLayer.setLocalDestinations(localDestinationInfos); - opt_device = opt_device || getCddTemplate('FooDevice', 'FooName'); + opt_device = opt_device || + print_preview_test_utils.getCddTemplate('FooDevice', 'FooName'); nativeLayer.setLocalDestinationCapabilities(opt_device); printPreview.initialize(); @@ -107,70 +108,6 @@ } /** - * @param {string} printerId - * @param {string=} opt_printerName Defaults to an empty string. - * @return {!print_preview.PrinterCapabilitiesResponse} - */ - function getCddTemplate(printerId, opt_printerName) { - return { - printer: { - deviceName: printerId, - printerName: opt_printerName || '', - }, - capabilities: { - version: '1.0', - printer: { - supported_content_type: [{content_type: 'application/pdf'}], - collate: {}, - color: { - option: [ - {type: 'STANDARD_COLOR', is_default: true}, - {type: 'STANDARD_MONOCHROME'} - ] - }, - copies: {}, - dpi: { - option: [ - {horizontal_dpi: 200, vertical_dpi: 200, is_default: true}, - {horizontal_dpi: 100, vertical_dpi: 100}, - ] - }, - duplex: { - option: [ - {type: 'NO_DUPLEX', is_default: true}, - {type: 'LONG_EDGE'}, - {type: 'SHORT_EDGE'} - ] - }, - page_orientation: { - option: [ - {type: 'PORTRAIT', is_default: true}, - {type: 'LANDSCAPE'}, - {type: 'AUTO'} - ] - }, - media_size: { - option: [ - { name: 'NA_LETTER', - width_microns: 215900, - height_microns: 279400, - is_default: true, - custom_display_name: "Letter", - }, - { - name: 'CUSTOM_SQUARE', - width_microns: 215900, - height_microns: 215900, - custom_display_name: "CUSTOM_SQUARE", - } - ] - } - } - } - }; - } - - /** * @return {!print_preview.PrinterCapabilitiesResponse} The capabilities of * the Save as PDF destination. */ @@ -214,7 +151,8 @@ */ function getAppStateString() { const origin = cr.isChromeOS ? 'chrome_os' : 'local'; - const cdd = getCddTemplate('ID1', 'One').capabilities; + const cdd = + print_preview_test_utils.getCddTemplate('ID1', 'One').capabilities; return JSON.stringify({ version: 2, recentDestinations: [ @@ -293,7 +231,7 @@ * @return {!Object} */ function getCddTemplateWithAdvancedSettings(printerId) { - const template = getCddTemplate(printerId); + const template = print_preview_test_utils.getCddTemplate(printerId); template.capabilities.printer.vendor_capability = [{ display_name: 'Print Area', id: 'Print Area', @@ -326,6 +264,18 @@ } /** + * @param {!HTMLElement} headerFooter The header/footer settings section. + * @param {boolean} displayed Whether the header footer section should be + * displayed when the preview is done loading. + */ + function checkHeaderFooterOnLoad(headerFooter, displayed) { + return nativeLayer.whenCalled('getPreview').then(function() { + checkElementDisplayed(headerFooter, displayed); + return whenAnimationDone('more-settings'); + }); + } + + /** * Expand the 'More Settings' div to expose all options. */ function expandMoreSettings() { @@ -517,7 +467,8 @@ }, ], }); - nativeLayer.setLocalDestinationCapabilities(getCddTemplate('ID')); + nativeLayer.setLocalDestinationCapabilities( + print_preview_test_utils.getCddTemplate('ID')); setInitialSettings(); return nativeLayer.whenCalled('getInitialSettings'); }); @@ -536,7 +487,7 @@ // Set up capabilities for ID1. This should be the device that should hav // its capabilities fetched, since it is the most recent. If another // device is selected the native layer will reject the callback. - const device = getCddTemplate('ID1', 'One'); + const device = print_preview_test_utils.getCddTemplate('ID1', 'One'); return setupSettingsAndDestinationsWithCapabilities(device).then( function() { @@ -578,10 +529,12 @@ ]; initialSettings.printerName = 'ID3'; - const device = getCddTemplate('ID3', 'Three'); + const device = print_preview_test_utils.getCddTemplate('ID3', 'Three'); - nativeLayer.setLocalDestinationCapabilities(getCddTemplate('ID1', 'One')); - nativeLayer.setLocalDestinationCapabilities(getCddTemplate('ID2', 'Two')); + nativeLayer.setLocalDestinationCapabilities( + print_preview_test_utils.getCddTemplate('ID1', 'One')); + nativeLayer.setLocalDestinationCapabilities( + print_preview_test_utils.getCddTemplate('ID2', 'Two')); return setupSettingsAndDestinationsWithCapabilities(device).then( function() { nativeLayer.reset(); @@ -634,7 +587,7 @@ { printerName: 'Two', deviceName: 'ID2' }, { printerName: 'Three', deviceName: 'ID3' }, ]; - const device = getCddTemplate('ID1', 'One'); + const device = print_preview_test_utils.getCddTemplate('ID1', 'One'); return Promise.all([ setupSettingsAndDestinationsWithCapabilities(device), @@ -689,7 +642,9 @@ initialSettings.serializedDefaultDestinationSelectionRulesStr = JSON.stringify({namePattern: '.*Bar.*'}); return setupSettingsAndDestinationsWithCapabilities( - getCddTemplate('BarDevice', 'BarName')).then(function() { + print_preview_test_utils.getCddTemplate( + 'BarDevice', 'BarName')) + .then(function() { assertEquals('BarDevice', printPreview.destinationStore_.selectedDestination.id); }); @@ -698,7 +653,8 @@ test('SystemDialogLinkIsHiddenInAppKioskMode', function() { if (!cr.isChromeOS) initialSettings.isInAppKioskMode = true; - nativeLayer.setLocalDestinationCapabilities(getCddTemplate('FooDevice')); + nativeLayer.setLocalDestinationCapabilities( + print_preview_test_utils.getCddTemplate('FooDevice')); setInitialSettings(); return nativeLayer.whenCalled('getInitialSettings').then( function() { @@ -713,7 +669,7 @@ checkSectionVisible($('layout-settings'), false); checkSectionVisible($('color-settings'), false); checkSectionVisible($('copies-settings'), false); - const device = getCddTemplate('FooDevice'); + const device = print_preview_test_utils.getCddTemplate('FooDevice'); device.capabilities.printer.color = { option: [{is_default: true, type: 'STANDARD_COLOR'}] }; @@ -914,18 +870,19 @@ // Make sure that custom margins controls are properly set up. test('CustomMarginsControlsCheck', function() { return setupSettingsAndDestinationsWithCapabilities().then(function() { + nativeLayer.resetResolver('getPreview'); printPreview.printTicketStore_.marginsType.updateValue( print_preview.ticket_items.MarginsTypeValue.CUSTOM); - - ['left', 'top', 'right', 'bottom'].forEach(function(margin) { - const control = - $('preview-area').querySelector('.margin-control-' + margin); - assertNotEquals(null, control); - const input = control.querySelector('.margin-control-textbox'); - assertTrue(input.hasAttribute('aria-label')); - assertNotEquals('undefined', input.getAttribute('aria-label')); + return nativeLayer.whenCalled('getPreview').then(function() { + ['left', 'top', 'right', 'bottom'].forEach(function(margin) { + const control = + $('preview-area').querySelector('.margin-control-' + margin); + assertNotEquals(null, control); + const input = control.querySelector('.margin-control-textbox'); + assertTrue(input.hasAttribute('aria-label')); + assertNotEquals('undefined', input.getAttribute('aria-label')); + }); }); - return whenAnimationDone('more-settings'); }); }); @@ -945,14 +902,13 @@ checkElementDisplayed(headerFooter, true); + nativeLayer.resetResolver('getPreview'); printPreview.printTicketStore_.marginsType.updateValue( print_preview.ticket_items.MarginsTypeValue.CUSTOM); printPreview.printTicketStore_.customMargins.updateValue( new print_preview.Margins(0, 0, 0, 0)); - checkElementDisplayed(headerFooter, false); - - return whenAnimationDone('more-settings'); + return checkHeaderFooterOnLoad(headerFooter, false); }); }); @@ -972,14 +928,12 @@ checkElementDisplayed(headerFooter, true); + nativeLayer.resetResolver('getPreview'); printPreview.printTicketStore_.marginsType.updateValue( print_preview.ticket_items.MarginsTypeValue.CUSTOM); printPreview.printTicketStore_.customMargins.updateValue( new print_preview.Margins(36, 36, 36, 36)); - - checkElementDisplayed(headerFooter, true); - - return whenAnimationDone('more-settings'); + return checkHeaderFooterOnLoad(headerFooter, true); }); }); @@ -1000,14 +954,13 @@ checkElementDisplayed(headerFooter, true); + nativeLayer.resetResolver('getPreview'); printPreview.printTicketStore_.marginsType.updateValue( print_preview.ticket_items.MarginsTypeValue.CUSTOM); printPreview.printTicketStore_.customMargins.updateValue( new print_preview.Margins(0, 36, 0, 36)); - checkElementDisplayed(headerFooter, false); - - return whenAnimationDone('more-settings'); + return checkHeaderFooterOnLoad(headerFooter, false); }); }); @@ -1028,20 +981,19 @@ checkElementDisplayed(headerFooter, true); + nativeLayer.resetResolver('getPreview'); printPreview.printTicketStore_.marginsType.updateValue( print_preview.ticket_items.MarginsTypeValue.CUSTOM); printPreview.printTicketStore_.customMargins.updateValue( new print_preview.Margins(0, 36, 36, 36)); - checkElementDisplayed(headerFooter, true); - - return whenAnimationDone('more-settings'); + return checkHeaderFooterOnLoad(headerFooter, true); }); }); // Check header footer availability with small (label) page size. test('SmallPaperSizeHeaderFooter', function() { - const device = getCddTemplate('FooDevice'); + const device = print_preview_test_utils.getCddTemplate('FooDevice'); device.capabilities.printer.media_size = { 'option': [ {'name': 'SmallLabel', 'width_microns': 38100, @@ -1067,23 +1019,25 @@ checkElementDisplayed(headerFooter, true); // Small label should not + nativeLayer.resetResolver('getPreview'); printPreview.printTicketStore_.mediaSize.updateValue( device.capabilities.printer.media_size.option[0]); - checkElementDisplayed(headerFooter, false); + return nativeLayer.whenCalled('getPreview').then(function() { + checkElementDisplayed(headerFooter, false); - // Oriented in landscape, there should be enough space for - // header/footer. - printPreview.printTicketStore_.landscape.updateValue(true); - checkElementDisplayed(headerFooter, true); - - return whenAnimationDone('more-settings'); + // Oriented in landscape, there should be enough space for + // header/footer. + nativeLayer.resetResolver('getPreview'); + printPreview.printTicketStore_.landscape.updateValue(true); + return checkHeaderFooterOnLoad(headerFooter, true); + }); }); }); // Test that the color settings, one option, standard monochrome. test('ColorSettingsMonochrome', function() { // Only one option, standard monochrome. - const device = getCddTemplate('FooDevice'); + const device = print_preview_test_utils.getCddTemplate('FooDevice'); device.capabilities.printer.color = { 'option': [ {'is_default': true, 'type': 'STANDARD_MONOCHROME'} @@ -1101,7 +1055,7 @@ // Test that the color settings, one option, custom monochrome. test('ColorSettingsCustomMonochrome', function() { // Only one option, standard monochrome. - const device = getCddTemplate('FooDevice'); + const device = print_preview_test_utils.getCddTemplate('FooDevice'); device.capabilities.printer.color = { 'option': [ {'is_default': true, 'type': 'CUSTOM_MONOCHROME', @@ -1119,7 +1073,7 @@ // Test that the color settings, one option, standard color. test('ColorSettingsColor', function() { - const device = getCddTemplate('FooDevice'); + const device = print_preview_test_utils.getCddTemplate('FooDevice'); device.capabilities.printer.color = { 'option': [ {'is_default': true, 'type': 'STANDARD_COLOR'} @@ -1136,7 +1090,7 @@ // Test that the color settings, one option, custom color. test('ColorSettingsCustomColor', function() { - const device = getCddTemplate('FooDevice'); + const device = print_preview_test_utils.getCddTemplate('FooDevice'); device.capabilities.printer.color = { 'option': [ {'is_default': true, 'type': 'CUSTOM_COLOR', 'vendor_id': '42'} @@ -1153,7 +1107,7 @@ // Test that the color settings, two options, both standard, defaults to // color. test('ColorSettingsBothStandardDefaultColor', function() { - const device = getCddTemplate('FooDevice'); + const device = print_preview_test_utils.getCddTemplate('FooDevice'); device.capabilities.printer.color = { 'option': [ {'type': 'STANDARD_MONOCHROME'}, @@ -1175,7 +1129,7 @@ // Test that the color settings, two options, both standard, defaults to // monochrome. test('ColorSettingsBothStandardDefaultMonochrome', function() { - const device = getCddTemplate('FooDevice'); + const device = print_preview_test_utils.getCddTemplate('FooDevice'); device.capabilities.printer.color = { 'option': [ {'is_default': true, 'type': 'STANDARD_MONOCHROME'}, @@ -1197,7 +1151,7 @@ // Test that the color settings, two options, both custom, defaults to // color. test('ColorSettingsBothCustomDefaultColor', function() { - const device = getCddTemplate('FooDevice'); + const device = print_preview_test_utils.getCddTemplate('FooDevice'); device.capabilities.printer.color = { 'option': [ {'type': 'CUSTOM_MONOCHROME', 'vendor_id': '42'}, @@ -1233,7 +1187,7 @@ // Test to verify that duplex settings are set according to the printer // capabilities. test('DuplexSettingsFalse', function() { - const device = getCddTemplate('FooDevice'); + const device = print_preview_test_utils.getCddTemplate('FooDevice'); delete device.capabilities.printer.duplex; return setupSettingsAndDestinationsWithCapabilities(device) .then(function() { @@ -1263,7 +1217,7 @@ nativeLayer.reset(); // Setup capabilities for BarDevice. - const device = getCddTemplate('BarDevice'); + const device = print_preview_test_utils.getCddTemplate('BarDevice'); device.capabilities.printer.color = { 'option': [ {'is_default': true, 'type': 'STANDARD_MONOCHROME'} @@ -1288,7 +1242,8 @@ previewArea.checkPluginCompatibility_ = function() { return false; }; - nativeLayer.setLocalDestinationCapabilities(getCddTemplate('FooDevice')); + nativeLayer.setLocalDestinationCapabilities( + print_preview_test_utils.getCddTemplate('FooDevice')); setInitialSettings(); return nativeLayer.whenCalled('getInitialSettings').then(function() { const previewAreaEl = $('preview-area'); @@ -1319,7 +1274,7 @@ const customLocalizedMediaName = 'Vendor defined localized media name'; const customMediaName = 'Vendor defined media name'; - const device = getCddTemplate('FooDevice'); + const device = print_preview_test_utils.getCddTemplate('FooDevice'); device.capabilities.printer.media_size = { option: [ { name: 'CUSTOM', @@ -1412,17 +1367,24 @@ version: 2, recentDestinations: [1, 2, 3].map(function(i) { return { - id: 'ID' + i, origin: origin, account: '', - capabilities: getCddTemplate('ID' + i), displayName: '', - extensionId: '', extensionName: '' + id: 'ID' + i, + origin: origin, + account: '', + capabilities: print_preview_test_utils.getCddTemplate('ID' + i), + displayName: '', + extensionId: '', + extensionName: '' }; }), }); // Ensure all capabilities are available for fetch. - nativeLayer.setLocalDestinationCapabilities(getCddTemplate('ID1')); - nativeLayer.setLocalDestinationCapabilities(getCddTemplate('ID2')); - nativeLayer.setLocalDestinationCapabilities(getCddTemplate('ID3')); + nativeLayer.setLocalDestinationCapabilities( + print_preview_test_utils.getCddTemplate('ID1')); + nativeLayer.setLocalDestinationCapabilities( + print_preview_test_utils.getCddTemplate('ID2')); + nativeLayer.setLocalDestinationCapabilities( + print_preview_test_utils.getCddTemplate('ID3')); // For crbug.com/666595. If multiple destinations are fetched there may // be multiple preview requests. This verifies the first fetch is for @@ -1447,7 +1409,7 @@ // an error and that the preview dialog can be recovered by selecting a // new destination. test('InvalidSettingsError', function() { - const barDevice = getCddTemplate('BarDevice'); + const barDevice = print_preview_test_utils.getCddTemplate('BarDevice'); nativeLayer.setLocalDestinationCapabilities(barDevice); // FooDevice is the default printer, so will be selected for the initial @@ -1509,7 +1471,7 @@ mediaDefault.width_microns, ticket.mediaSize.width_microns); expectEquals( mediaDefault.height_microns, ticket.mediaSize.height_microns); - return nativeLayer.whenCalled('hidePreview'); + return nativeLayer.whenCalled('dialogClose'); }); }); @@ -1572,7 +1534,7 @@ { printerName: 'FooName', deviceName: 'FooDevice' } ]; nativeLayer.setLocalDestinationCapabilities( - getCddTemplate('ID1', 'One')); + print_preview_test_utils.getCddTemplate('ID1', 'One')); return setupSettingsAndDestinationsWithCapabilities().then(function() { // The system default destination should be used instead of the @@ -1599,7 +1561,7 @@ const openPdfPreviewLink = $('open-pdf-in-preview-link'); checkElementDisplayed(openPdfPreviewLink, true); openPdfPreviewLink.click(); - // Should result in a print call and dialog should hide + // Should result in a print call and dialog should close. return nativeLayer.whenCalled('print'); }).then( /** @@ -1608,7 +1570,7 @@ */ function(printTicket) { expectTrue(JSON.parse(printTicket).OpenPDFInPreview); - return nativeLayer.whenCalled('hidePreview'); + return nativeLayer.whenCalled('dialogClose'); }); }); @@ -1661,7 +1623,7 @@ const systemDialogLink = $('system-dialog-link'); checkElementDisplayed(systemDialogLink, true); systemDialogLink.click(); - // Should result in a print call and dialog should hide + // Should result in a print call and dialog should close. return nativeLayer.whenCalled('print'); }).then( /** @@ -1670,7 +1632,7 @@ */ function(printTicket) { expectTrue(JSON.parse(printTicket).showSystemDialog); - return nativeLayer.whenCalled('hidePreview'); + return nativeLayer.whenCalled('dialogClose'); }); }); @@ -1712,6 +1674,5 @@ return { suiteName: suiteName, - getCddTemplate: getCddTemplate, }; });
diff --git a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js index c7b317be..079d936 100644 --- a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js +++ b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
@@ -4,7 +4,7 @@ /** @fileoverview Runs the Print Preview tests. */ -var ROOT_PATH = '../../../../../'; +const ROOT_PATH = '../../../../../'; /** * @constructor @@ -59,6 +59,7 @@ 'print_preview_tests.js', 'native_layer_stub.js', 'plugin_stub.js', + 'print_preview_test_utils.js', ], }; @@ -97,7 +98,9 @@ 'NoPDFPluginErrorMessage', 'CustomPaperNames', 'InitIssuesOneRequest', - 'InvalidSettingsError', + // TODO(https://crbug.com/795626): Re-enable this test when test flakiness on + // the Mac bot is fixed. + 'DISABLED_InvalidSettingsError', // TODO(thestig): Re-enable this test when the feature works properly. // https://crbug.com/746768 'DISABLED_GenerateDraft',
diff --git a/chrome/test/data/webui/print_preview/restore_state_test.js b/chrome/test/data/webui/print_preview/restore_state_test.js index 39b6361e..1c6af97 100644 --- a/chrome/test/data/webui/print_preview/restore_state_test.js +++ b/chrome/test/data/webui/print_preview/restore_state_test.js
@@ -72,7 +72,7 @@ nativeLayer.setInitialSettings(initialSettings); nativeLayer.setLocalDestinationCapabilities( - print_preview_test.getCddTemplate(initialSettings.printerName)); + print_preview_test_utils.getCddTemplate(initialSettings.printerName)); page = document.createElement('print-preview-app'); document.body.appendChild(page);
diff --git a/chrome/test/data/webui/print_preview/settings_section_test.js b/chrome/test/data/webui/print_preview/settings_section_test.js index 1ee69a2..95b0ad7 100644 --- a/chrome/test/data/webui/print_preview/settings_section_test.js +++ b/chrome/test/data/webui/print_preview/settings_section_test.js
@@ -24,60 +24,16 @@ PolymerTest.clearBody(); page = document.createElement('print-preview-app'); document.body.appendChild(page); - }); - /** @return {!print_preview.Cdd} */ - function getCdd() { - return { - version: '1.0', - printer: { - collate: {default: true}, - copies: {default: 1, max: 1000}, - color: { - option: [ - {type: 'STANDARD_COLOR', is_default: true}, - {type: 'STANDARD_MONOCHROME'} - ] - }, - dpi: { - option: [ - {horizontal_dpi: 200, vertical_dpi: 200, is_default: true}, - {horizontal_dpi: 100, vertical_dpi: 100}, - ] - }, - duplex: { - option: [ - {type: 'NO_DUPLEX', is_default: true}, {type: 'LONG_EDGE'}, - {type: 'SHORT_EDGE'} - ] - }, - page_orientation: { - option: [ - {type: 'PORTRAIT', is_default: true}, {type: 'LANDSCAPE'}, - {type: 'AUTO'} - ] - }, - media_size: { - option: [ - { - name: 'NA_LETTER', - width_microns: 215900, - height_microns: 279400, - is_default: true, - custom_display_name: 'Letter', - }, - { - name: 'CUSTOM_SQUARE', - width_microns: 215900, - height_microns: 215900, - custom_display_name: 'CUSTOM_SQUARE', - } - ] - }, - vendor_capability: [], - }, - }; - } + const fooDestination = new print_preview.Destination( + 'FooPrinter', print_preview.DestinationType.LOCAL, + print_preview.DestinationOrigin.LOCAL, 'Foo Printer', + false /*isRecent*/, print_preview.DestinationConnectionStatus.ONLINE); + fooDestination.capabilities = + print_preview_test_utils.getCddTemplate(fooDestination.id) + .capabilities; + page.set('destination_', fooDestination); + }); /** @param {boolean} isPdf Whether the document should be a PDF. */ function setPdfDocument(isPdf) { @@ -93,7 +49,9 @@ print_preview.DestinationOrigin.LOCAL, loadTimeData.getString('printToPDF'), false /*isRecent*/, print_preview.DestinationConnectionStatus.ONLINE); - saveAsPdfDestination.capabilities = getCdd(); + saveAsPdfDestination.capabilities = + print_preview_test_utils.getCddTemplate(saveAsPdfDestination.id) + .capabilities; page.set('destination_', saveAsPdfDestination); } @@ -102,7 +60,8 @@ expectEquals(false, copiesElement.hidden); // Remove copies capability. - const capabilities = getCdd(); + let capabilities = + print_preview_test_utils.getCddTemplate('FooPrinter').capabilities; delete capabilities.printer.copies; // Copies section should now be hidden. @@ -118,16 +77,16 @@ expectEquals(false, layoutElement.hidden); // Remove layout capability. - let capabilities = getCdd(); + let capabilities = + print_preview_test_utils.getCddTemplate('FooPrinter').capabilities; delete capabilities.printer.page_orientation; // Each of these settings should not show the capability. - [ - null, - {option: [{ type: 'PORTRAIT', is_default: true }]}, - {option: [{ type: 'LANDSCAPE', is_default: true}]}, + [null, {option: [{type: 'PORTRAIT', is_default: true}]}, + {option: [{type: 'LANDSCAPE', is_default: true}]}, ].forEach(layoutCap => { - capabilities = getCdd(); + capabilities = + print_preview_test_utils.getCddTemplate('FooPrinter').capabilities; capabilities.printer.page_orientation = layoutCap; // Layout section should now be hidden. page.set('destination_.capabilities', capabilities); @@ -135,7 +94,8 @@ }); // Reset full capabilities - capabilities = getCdd(); + capabilities = + print_preview_test_utils.getCddTemplate('FooPrinter').capabilities; page.set('destination_.capabilities', capabilities); expectEquals(false, layoutElement.hidden); @@ -149,20 +109,26 @@ expectEquals(false, colorElement.hidden); // Remove color capability. - let capabilities = getCdd(); + let capabilities = + print_preview_test_utils.getCddTemplate('FooPrinter').capabilities; delete capabilities.printer.color; // Each of these settings should not show the capability. - [ - null, - {option: [{ type: 'STANDARD_COLOR', is_default: true }]}, - {option: [{ type: 'STANDARD_COLOR', is_default: true }, - { type: 'CUSTOM_COLOR'}]}, - {option: [{ type: 'STANDARD_MONOCHROME', is_default: true }, - { type: 'CUSTOM_MONOCHROME' }]}, - {option: [{ type: 'STANDARD_MONOCHROME', is_default: true}]}, + [null, {option: [{type: 'STANDARD_COLOR', is_default: true}]}, { + option: [ + {type: 'STANDARD_COLOR', is_default: true}, {type: 'CUSTOM_COLOR'} + ] + }, + { + option: [ + {type: 'STANDARD_MONOCHROME', is_default: true}, + {type: 'CUSTOM_MONOCHROME'} + ] + }, + {option: [{type: 'STANDARD_MONOCHROME', is_default: true}]}, ].forEach(colorCap => { - capabilities = getCdd(); + capabilities = + print_preview_test_utils.getCddTemplate('FooPrinter').capabilities; capabilities.printer.color = colorCap; // Layout section should now be hidden. page.set('destination_.capabilities', capabilities); @@ -170,7 +136,8 @@ }); // Custom color and monochrome options should make the section visible. - capabilities = getCdd(); + capabilities = + print_preview_test_utils.getCddTemplate('FooPrinter').capabilities; capabilities.printer.color = {option: [{ type: 'CUSTOM_COLOR', is_default: true }, { type: 'CUSTOM_MONOCHROME' }]}; @@ -183,7 +150,8 @@ expectEquals(false, mediaSizeElement.hidden); // Remove capability. - let capabilities = getCdd(); + let capabilities = + print_preview_test_utils.getCddTemplate('FooPrinter').capabilities; delete capabilities.printer.media_size; // Section should now be hidden. @@ -191,7 +159,8 @@ expectEquals(true, mediaSizeElement.hidden); // Reset - capabilities = getCdd(); + capabilities = + print_preview_test_utils.getCddTemplate('FooPrinter').capabilities; page.set('destination_.capabilities', capabilities); // Set PDF document type. @@ -224,7 +193,8 @@ expectEquals(false, dpiElement.hidden); // Remove capability. - let capabilities = getCdd(); + let capabilities = + print_preview_test_utils.getCddTemplate('FooPrinter').capabilities; delete capabilities.printer.dpi; // Section should now be hidden. @@ -232,7 +202,8 @@ expectEquals(true, dpiElement.hidden); // Does not show up for only 1 option. - capabilities = getCdd(); + capabilities = + print_preview_test_utils.getCddTemplate('FooPrinter').capabilities; capabilities.printer.dpi.option.pop(); page.set('destination_.capabilities', capabilities); expectEquals(true, dpiElement.hidden); @@ -273,7 +244,8 @@ // Start with HTML + duplex capability. setPdfDocument(false); - let capabilities = getCdd(); + let capabilities = + print_preview_test_utils.getCddTemplate('FooPrinter').capabilities; page.set('destination_.capabilities', capabilities); expectEquals(false, optionsElement.hidden); expectEquals(false, headerFooter.hidden); @@ -290,7 +262,8 @@ expectEquals(false, selectionOnly.hidden); // Remove duplex capability. - capabilities = getCdd(); + capabilities = + print_preview_test_utils.getCddTemplate('FooPrinter').capabilities; delete capabilities.printer.duplex; page.set('destination_.capabilities', capabilities); expectEquals(false, optionsElement.hidden); @@ -313,7 +286,8 @@ expectEquals(true, selectionOnly.hidden); // Add duplex. - capabilities = getCdd(); + capabilities = + print_preview_test_utils.getCddTemplate('FooPrinter').capabilities; page.set('destination_.capabilities', capabilities); expectEquals(false, optionsElement.hidden); expectEquals(false, duplex.hidden);
diff --git a/chrome/utility/BUILD.gn b/chrome/utility/BUILD.gn index 8f474fb..c9eea93 100644 --- a/chrome/utility/BUILD.gn +++ b/chrome/utility/BUILD.gn
@@ -184,15 +184,6 @@ "printing_handler.cc", "printing_handler.h", ] - deps += [ "//pdf" ] - if (is_win) { - sources += [ - "printing/pdf_to_emf_converter_factory_impl.cc", - "printing/pdf_to_emf_converter_factory_impl.h", - "printing/pdf_to_emf_converter_impl.cc", - "printing/pdf_to_emf_converter_impl.h", - ] - } } if (enable_basic_printing || enable_print_preview) {
diff --git a/chrome/utility/chrome_content_utility_client.cc b/chrome/utility/chrome_content_utility_client.cc index 20a12a2..f1f5d91 100644 --- a/chrome/utility/chrome_content_utility_client.cc +++ b/chrome/utility/chrome_content_utility_client.cc
@@ -46,7 +46,6 @@ #if defined(OS_WIN) #include "chrome/services/util_win/public/interfaces/constants.mojom.h" #include "chrome/services/util_win/util_win_service.h" -#include "chrome/utility/printing/pdf_to_emf_converter_factory_impl.h" #endif #if BUILDFLAG(ENABLE_EXTENSIONS) @@ -179,11 +178,6 @@ registry->AddInterface(base::Bind(CreateResourceUsageReporter), base::ThreadTaskRunnerHandle::Get()); #endif // !defined(OS_ANDROID) -#if defined(OS_WIN) - registry->AddInterface( - base::Bind(printing::PdfToEmfConverterFactoryImpl::Create), - base::ThreadTaskRunnerHandle::Get()); -#endif } connection->AddConnectionFilter(
diff --git a/chrome/utility/printing/pdf_to_emf_converter_factory_impl.cc b/chrome/utility/printing/pdf_to_emf_converter_factory_impl.cc deleted file mode 100644 index 6dff90e..0000000 --- a/chrome/utility/printing/pdf_to_emf_converter_factory_impl.cc +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/utility/printing/pdf_to_emf_converter_factory_impl.h" - -#include "chrome/utility/printing/pdf_to_emf_converter_impl.h" -#include "mojo/public/cpp/bindings/strong_binding.h" -#include "mojo/public/cpp/system/platform_handle.h" - -namespace printing { - -PdfToEmfConverterFactoryImpl::PdfToEmfConverterFactoryImpl() = default; - -PdfToEmfConverterFactoryImpl::~PdfToEmfConverterFactoryImpl() = default; - -void PdfToEmfConverterFactoryImpl::CreateConverter( - mojo::ScopedHandle pdf_file_in, - const printing::PdfRenderSettings& render_settings, - mojom::PdfToEmfConverterClientPtr client, - CreateConverterCallback callback) { - auto converter = std::make_unique<PdfToEmfConverterImpl>( - std::move(pdf_file_in), render_settings, std::move(client)); - uint32_t page_count = converter->total_page_count(); - mojom::PdfToEmfConverterPtr converter_ptr; - mojo::MakeStrongBinding(std::move(converter), - mojo::MakeRequest(&converter_ptr)); - - std::move(callback).Run(std::move(converter_ptr), page_count); -} - -// static -void PdfToEmfConverterFactoryImpl::Create( - mojom::PdfToEmfConverterFactoryRequest request) { - mojo::MakeStrongBinding(base::MakeUnique<PdfToEmfConverterFactoryImpl>(), - std::move(request)); -} - -} // namespace printing
diff --git a/chrome/utility/printing/pdf_to_emf_converter_factory_impl.h b/chrome/utility/printing/pdf_to_emf_converter_factory_impl.h deleted file mode 100644 index 791addc..0000000 --- a/chrome/utility/printing/pdf_to_emf_converter_factory_impl.h +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_UTILITY_PRINTING_PDF_TO_EMF_CONVERTER_FACTORY_IMPL_H_ -#define CHROME_UTILITY_PRINTING_PDF_TO_EMF_CONVERTER_FACTORY_IMPL_H_ - -#include "base/macros.h" -#include "chrome/common/printing/pdf_to_emf_converter.mojom.h" - -namespace printing { - -class PdfToEmfConverterFactoryImpl : public mojom::PdfToEmfConverterFactory { - public: - PdfToEmfConverterFactoryImpl(); - ~PdfToEmfConverterFactoryImpl() override; - - static void Create(mojom::PdfToEmfConverterFactoryRequest request); - - private: - // mojom::PdfToEmfConverterFactory implementation. - void CreateConverter(mojo::ScopedHandle pdf_file_in, - const printing::PdfRenderSettings& render_settings, - mojom::PdfToEmfConverterClientPtr client, - CreateConverterCallback callback) override; - - DISALLOW_COPY_AND_ASSIGN(PdfToEmfConverterFactoryImpl); -}; - -} // namespace printing - -#endif // CHROME_UTILITY_PRINTING_PDF_TO_EMF_CONVERTER_FACTORY_IMPL_H_
diff --git a/chromecast/tools/trace.py b/chromecast/tools/trace.py index 9342e600..5f9f39f 100755 --- a/chromecast/tools/trace.py +++ b/chromecast/tools/trace.py
@@ -22,7 +22,7 @@ if options.adb_device: backend = TracingBackendAndroid(options.adb_device) else: - backend = TracingBackend(options.device, options.port, 10, 0) + backend = TracingBackend(options.device, options.port, options.timeout, 0) try: backend.Connect() @@ -57,6 +57,9 @@ default='127.0.0.1') parser.add_option( '-s', '--adb-device', help='Device serial for adb.', type='string') + parser.add_option( + '-t', '--timeout', help='Websocket timeout interval.', type='int', + default=90) tracing_opts = optparse.OptionGroup(parser, 'Tracing options') tracing_opts.add_option( @@ -75,7 +78,7 @@ help='Enable system tracing.', action='store_true', dest='systrace', - default=False) + default=True) parser.add_option_group(tracing_opts) output_options = optparse.OptionGroup(parser, 'Output options')
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 1c8e1879..bf0f9ce 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -10216.0.0 \ No newline at end of file +10222.0.0 \ No newline at end of file
diff --git a/chromeos/attestation/attestation_constants.h b/chromeos/attestation/attestation_constants.h index 2600b7c..55ee9a5 100644 --- a/chromeos/attestation/attestation_constants.h +++ b/chromeos/attestation/attestation_constants.h
@@ -51,6 +51,16 @@ PROFILE_ENTERPRISE_ENROLLMENT_CERTIFICATE = 7 }; +// Status for operations involving an attestation server. +enum AttestationStatus { + // Call successful + ATTESTATION_SUCCESS, + // Failure, no specific reason + ATTESTATION_UNSPECIFIED_FAILURE, + // Failure, sending a bad request to an attestation server + ATTESTATION_SERVER_BAD_REQUEST_FAILURE +}; + enum PrivacyCAType { DEFAULT_PCA, // The Google-operated Privacy CA. TEST_PCA, // The test version of the Google-operated Privacy CA.
diff --git a/chromeos/attestation/attestation_flow.cc b/chromeos/attestation/attestation_flow.cc index 05aee62..2ae897b0 100644 --- a/chromeos/attestation/attestation_flow.cc +++ b/chromeos/attestation/attestation_flow.cc
@@ -54,17 +54,20 @@ task.Run(); } -void DBusDataMethodCallback( +void DBusCertificateMethodCallback( const AttestationFlow::CertificateCallback& callback, base::Optional<CryptohomeClient::TpmAttestationDataResult> result) { if (!result.has_value()) { LOG(ERROR) << "Attestation: DBus data operation failed."; if (!callback.is_null()) - callback.Run(false, ""); + callback.Run(ATTESTATION_UNSPECIFIED_FAILURE, ""); return; } - if (!callback.is_null()) - callback.Run(result->success, result->data); + if (!callback.is_null()) { + callback.Run( + result->success ? ATTESTATION_SUCCESS : ATTESTATION_UNSPECIFIED_FAILURE, + result->data); + } } } // namespace @@ -123,7 +126,8 @@ const base::Closure do_cert_request = base::Bind( &AttestationFlow::StartCertificateRequest, weak_factory_.GetWeakPtr(), certificate_profile, account_id, request_origin, force_new_key, callback); - const base::Closure on_failure = base::Bind(callback, false, ""); + const base::RepeatingClosure on_failure = + base::BindRepeating(callback, ATTESTATION_UNSPECIFIED_FAILURE, ""); const base::Closure initiate_enroll = base::Bind( &AttestationFlow::WaitForAttestationReadyAndStartEnroll, weak_factory_.GetWeakPtr(), base::TimeTicks::Now() + ready_timeout_, @@ -247,9 +251,10 @@ certificate_profile, account_id, request_origin, true, callback); cryptohome_client_->TpmAttestationDoesKeyExist( key_type, cryptohome::Identification(account_id), key_name, - base::Bind(&DBusBoolRedirectCallback, on_key_exists, on_key_not_exists, - base::Bind(callback, false, ""), - "check for existence of attestation key")); + base::BindRepeating( + &DBusBoolRedirectCallback, on_key_exists, on_key_not_exists, + base::BindRepeating(callback, ATTESTATION_UNSPECIFIED_FAILURE, ""), + "check for existence of attestation key")); } } @@ -263,7 +268,7 @@ if (!success) { LOG(ERROR) << "Attestation: Failed to create certificate request."; if (!callback.is_null()) - callback.Run(false, ""); + callback.Run(ATTESTATION_UNSPECIFIED_FAILURE, ""); return; } @@ -284,14 +289,24 @@ if (!success) { LOG(ERROR) << "Attestation: Certificate request failed."; if (!callback.is_null()) - callback.Run(false, ""); + callback.Run(ATTESTATION_UNSPECIFIED_FAILURE, ""); return; } // Forward the response to the attestation service to complete the operation. async_caller_->AsyncTpmAttestationFinishCertRequest( data, key_type, cryptohome::Identification(account_id), key_name, - callback); + base::BindRepeating(&AttestationFlow::OnCertRequestFinished, + weak_factory_.GetWeakPtr(), callback)); +} + +void AttestationFlow::OnCertRequestFinished(const CertificateCallback& callback, + bool success, + const std::string& data) { + if (success) + callback.Run(ATTESTATION_SUCCESS, data); + else + callback.Run(ATTESTATION_SERVER_BAD_REQUEST_FAILURE, data); } void AttestationFlow::GetExistingCertificate( @@ -301,7 +316,7 @@ const CertificateCallback& callback) { cryptohome_client_->TpmAttestationGetCertificate( key_type, cryptohome::Identification(account_id), key_name, - base::Bind(&DBusDataMethodCallback, callback)); + base::BindRepeating(&DBusCertificateMethodCallback, callback)); } void AttestationFlow::CheckAttestationReadyAndReschedule(
diff --git a/chromeos/attestation/attestation_flow.h b/chromeos/attestation/attestation_flow.h index d77e6cb..7f0a7bc 100644 --- a/chromeos/attestation/attestation_flow.h +++ b/chromeos/attestation/attestation_flow.h
@@ -58,8 +58,8 @@ // This class is not thread safe. class CHROMEOS_EXPORT AttestationFlow { public: - typedef base::Callback<void(bool success, - const std::string& pem_certificate_chain)> + typedef base::RepeatingCallback< + void(AttestationStatus status, const std::string& pem_certificate_chain)> CertificateCallback; // Returns the attestation key type for a given |certificate_profile|. @@ -243,6 +243,16 @@ bool success, const std::string& data); + // Called after cryptohome finishes processing of a certificate request. + // + // Parameters + // callback - Called when the operation completes. + // success - The status of request finishing. + // data - The certificate data in PEM format. + void OnCertRequestFinished(const CertificateCallback& callback, + bool success, + const std::string& data); + // Gets an existing certificate from the attestation daemon. // // Parameters
diff --git a/chromeos/attestation/attestation_flow_unittest.cc b/chromeos/attestation/attestation_flow_unittest.cc index 700ff6f1..f4ee23e 100644 --- a/chromeos/attestation/attestation_flow_unittest.cc +++ b/chromeos/attestation/attestation_flow_unittest.cc
@@ -45,12 +45,12 @@ public: void QuitRunLoopCertificateCallback( const AttestationFlow::CertificateCallback& callback, - bool success, + AttestationStatus status, const std::string& cert) { LOG(WARNING) << "Quitting run loop."; run_loop_->Quit(); if (!callback.is_null()) - callback.Run(success, cert); + callback.Run(status, cert); } protected: @@ -130,10 +130,10 @@ .InSequence(flow_order); StrictMock<MockObserver> observer; - EXPECT_CALL( - observer, - MockCertificateCallback( - true, cryptohome::MockAsyncMethodCaller::kFakeAttestationCert)) + EXPECT_CALL(observer, + MockCertificateCallback( + ATTESTATION_SUCCESS, + cryptohome::MockAsyncMethodCaller::kFakeAttestationCert)) .Times(1) .InSequence(flow_order); AttestationFlow::CertificateCallback mock_callback = base::Bind( @@ -211,9 +211,10 @@ kEnterpriseUserKey, _)); StrictMock<MockObserver> observer; - EXPECT_CALL(observer, MockCertificateCallback( - true, - cryptohome::MockAsyncMethodCaller::kFakeAttestationCert)) + EXPECT_CALL(observer, + MockCertificateCallback( + ATTESTATION_SUCCESS, + cryptohome::MockAsyncMethodCaller::kFakeAttestationCert)) .Times(1) .InSequence(flow_order); AttestationFlow::CertificateCallback callback = base::Bind( @@ -243,7 +244,9 @@ EXPECT_CALL(*proxy, GetType()).WillRepeatedly(DoDefault()); StrictMock<MockObserver> observer; - EXPECT_CALL(observer, MockCertificateCallback(false, "")).Times(1); + EXPECT_CALL(observer, + MockCertificateCallback(ATTESTATION_UNSPECIFIED_FAILURE, "")) + .Times(1); AttestationFlow::CertificateCallback callback = base::Bind( &AttestationFlowTest::QuitRunLoopCertificateCallback, base::Unretained(this), base::Bind(&MockObserver::MockCertificateCallback, @@ -274,7 +277,8 @@ EXPECT_CALL(*proxy, GetType()).WillRepeatedly(DoDefault()); StrictMock<MockObserver> observer; - EXPECT_CALL(observer, MockCertificateCallback(false, "")) + EXPECT_CALL(observer, + MockCertificateCallback(ATTESTATION_UNSPECIFIED_FAILURE, "")) .Times(1); AttestationFlow::CertificateCallback mock_callback = base::Bind( &MockObserver::MockCertificateCallback, @@ -305,7 +309,8 @@ _)).Times(1); StrictMock<MockObserver> observer; - EXPECT_CALL(observer, MockCertificateCallback(false, "")) + EXPECT_CALL(observer, + MockCertificateCallback(ATTESTATION_UNSPECIFIED_FAILURE, "")) .Times(1); AttestationFlow::CertificateCallback mock_callback = base::Bind( &MockObserver::MockCertificateCallback, @@ -342,7 +347,9 @@ _)).Times(1); StrictMock<MockObserver> observer; - EXPECT_CALL(observer, MockCertificateCallback(false, "")).Times(1); + EXPECT_CALL(observer, + MockCertificateCallback(ATTESTATION_UNSPECIFIED_FAILURE, "")) + .Times(1); AttestationFlow::CertificateCallback mock_callback = base::Bind( &MockObserver::MockCertificateCallback, base::Unretained(&observer)); @@ -380,9 +387,11 @@ _)).Times(1); StrictMock<MockObserver> observer; - EXPECT_CALL(observer, MockCertificateCallback( - true, - cryptohome::MockAsyncMethodCaller::kFakeAttestationCert)).Times(1); + EXPECT_CALL(observer, + MockCertificateCallback( + ATTESTATION_SUCCESS, + cryptohome::MockAsyncMethodCaller::kFakeAttestationCert)) + .Times(1); AttestationFlow::CertificateCallback mock_callback = base::Bind( &MockObserver::MockCertificateCallback, base::Unretained(&observer)); @@ -409,7 +418,9 @@ EXPECT_CALL(*proxy, GetType()).WillRepeatedly(DoDefault()); StrictMock<MockObserver> observer; - EXPECT_CALL(observer, MockCertificateCallback(false, "")).Times(1); + EXPECT_CALL(observer, + MockCertificateCallback(ATTESTATION_UNSPECIFIED_FAILURE, "")) + .Times(1); AttestationFlow::CertificateCallback mock_callback = base::Bind( &MockObserver::MockCertificateCallback, base::Unretained(&observer)); @@ -439,7 +450,48 @@ _)).Times(1); StrictMock<MockObserver> observer; - EXPECT_CALL(observer, MockCertificateCallback(false, "")).Times(1); + EXPECT_CALL(observer, + MockCertificateCallback(ATTESTATION_UNSPECIFIED_FAILURE, "")) + .Times(1); + AttestationFlow::CertificateCallback mock_callback = base::BindRepeating( + &MockObserver::MockCertificateCallback, base::Unretained(&observer)); + + std::unique_ptr<ServerProxy> proxy_interface(proxy.release()); + AttestationFlow flow(&async_caller, &client, std::move(proxy_interface)); + flow.GetCertificate(PROFILE_ENTERPRISE_USER_CERTIFICATE, EmptyAccountId(), "", + true, mock_callback); + RunUntilIdle(); +} + +TEST_F(AttestationFlowTest, GetCertificate_CertRequestBadRequest) { + StrictMock<cryptohome::MockAsyncMethodCaller> async_caller; + async_caller.SetUp(true, cryptohome::MOUNT_ERROR_NONE); + EXPECT_CALL(async_caller, AsyncTpmAttestationCreateCertRequest( + _, PROFILE_ENTERPRISE_USER_CERTIFICATE, + cryptohome::Identification(), "", _)) + .Times(1); + + chromeos::FakeCryptohomeClient client; + + std::unique_ptr<MockServerProxy> proxy(new StrictMock<MockServerProxy>()); + proxy->DeferToFake(true); + EXPECT_CALL(*proxy, GetType()).WillRepeatedly(DoDefault()); + EXPECT_CALL( + *proxy, + SendCertificateRequest( + cryptohome::MockAsyncMethodCaller::kFakeAttestationCertRequest, _)) + .Times(1); + EXPECT_CALL(async_caller, AsyncTpmAttestationFinishCertRequest(_, _, _, _, _)) + .Times(1) + .WillOnce(WithArgs<4>(Invoke( + [](const cryptohome::AsyncMethodCaller::DataCallback& callback) { + callback.Run(false, ""); + }))); + + StrictMock<MockObserver> observer; + EXPECT_CALL(observer, MockCertificateCallback( + ATTESTATION_SERVER_BAD_REQUEST_FAILURE, "")) + .Times(1); AttestationFlow::CertificateCallback mock_callback = base::Bind( &MockObserver::MockCertificateCallback, base::Unretained(&observer)); @@ -463,7 +515,9 @@ EXPECT_CALL(*proxy, GetType()).WillRepeatedly(DoDefault()); StrictMock<MockObserver> observer; - EXPECT_CALL(observer, MockCertificateCallback(false, "")).Times(1); + EXPECT_CALL(observer, + MockCertificateCallback(ATTESTATION_UNSPECIFIED_FAILURE, "")) + .Times(1); AttestationFlow::CertificateCallback mock_callback = base::Bind( &MockObserver::MockCertificateCallback, base::Unretained(&observer)); @@ -501,9 +555,11 @@ _)).Times(1); StrictMock<MockObserver> observer; - EXPECT_CALL(observer, MockCertificateCallback( - true, - cryptohome::MockAsyncMethodCaller::kFakeAttestationCert)).Times(1); + EXPECT_CALL(observer, + MockCertificateCallback( + ATTESTATION_SUCCESS, + cryptohome::MockAsyncMethodCaller::kFakeAttestationCert)) + .Times(1); AttestationFlow::CertificateCallback mock_callback = base::Bind( &MockObserver::MockCertificateCallback, base::Unretained(&observer)); @@ -528,7 +584,9 @@ EXPECT_CALL(*proxy, GetType()).WillRepeatedly(DoDefault()); StrictMock<MockObserver> observer; - EXPECT_CALL(observer, MockCertificateCallback(true, "fake_cert")).Times(1); + EXPECT_CALL(observer, + MockCertificateCallback(ATTESTATION_SUCCESS, "fake_cert")) + .Times(1); AttestationFlow::CertificateCallback mock_callback = base::Bind( &MockObserver::MockCertificateCallback, base::Unretained(&observer));
diff --git a/chromeos/attestation/mock_attestation_flow.h b/chromeos/attestation/mock_attestation_flow.h index d64548e..242c8475 100644 --- a/chromeos/attestation/mock_attestation_flow.h +++ b/chromeos/attestation/mock_attestation_flow.h
@@ -60,7 +60,8 @@ MockObserver(); virtual ~MockObserver(); - MOCK_METHOD2(MockCertificateCallback, void(bool, const std::string&)); + MOCK_METHOD2(MockCertificateCallback, + void(AttestationStatus, const std::string&)); }; class MockAttestationFlow : public AttestationFlow {
diff --git a/chromeos/cryptohome/async_method_caller.cc b/chromeos/cryptohome/async_method_caller.cc index edef400f..34953fe 100644 --- a/chromeos/cryptohome/async_method_caller.cc +++ b/chromeos/cryptohome/async_method_caller.cc
@@ -270,6 +270,7 @@ base::Bind(it->second.data_callback, return_status, return_data)); data_callback_map_.erase(it); } + // Registers a callback which is called when the result for AsyncXXX is ready. void RegisterAsyncCallback(Callback callback, const char* error,
diff --git a/chromeos/dbus/auth_policy_client.cc b/chromeos/dbus/auth_policy_client.cc index 0084fbd..1d176a1 100644 --- a/chromeos/dbus/auth_policy_client.cc +++ b/chromeos/dbus/auth_policy_client.cc
@@ -98,12 +98,16 @@ weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } - void GetUserStatus(const std::string& object_guid, + void GetUserStatus(const authpolicy::GetUserStatusRequest& request, GetUserStatusCallback callback) override { dbus::MethodCall method_call(authpolicy::kAuthPolicyInterface, authpolicy::kGetUserStatusMethod); dbus::MessageWriter writer(&method_call); - writer.AppendString(object_guid); + if (!writer.AppendProtoAsArrayOfBytes(request)) { + std::move(callback).Run(authpolicy::ERROR_DBUS_FAILURE, + authpolicy::ActiveDirectoryUserStatus()); + return; + } proxy_->CallMethod( &method_call, kSlowDbusTimeoutMilliseconds, base::BindOnce(&AuthPolicyClientImpl::HandleCallback<
diff --git a/chromeos/dbus/auth_policy_client.h b/chromeos/dbus/auth_policy_client.h index e8e0164..68b157c 100644 --- a/chromeos/dbus/auth_policy_client.h +++ b/chromeos/dbus/auth_policy_client.h
@@ -60,9 +60,9 @@ AuthCallback callback) = 0; // Calls GetUserStatus. If Active Directory server is online it fetches - // ActiveDirectoryUserStatus for the user specified by |object_guid|. + // ActiveDirectoryUserStatus for the user specified by |request|. // |callback| is called after getting (or failing to get) D-Bus response. - virtual void GetUserStatus(const std::string& object_guid, + virtual void GetUserStatus(const authpolicy::GetUserStatusRequest& request, GetUserStatusCallback callback) = 0; // Calls GetUserKerberosFiles. If authpolicyd has Kerberos files for the user
diff --git a/chromeos/dbus/fake_auth_policy_client.cc b/chromeos/dbus/fake_auth_policy_client.cc index 80c9e81..fc0a1e1a 100644 --- a/chromeos/dbus/fake_auth_policy_client.cc +++ b/chromeos/dbus/fake_auth_policy_client.cc
@@ -152,15 +152,16 @@ dbus_operation_delay_); } -void FakeAuthPolicyClient::GetUserStatus(const std::string& object_guid, - GetUserStatusCallback callback) { +void FakeAuthPolicyClient::GetUserStatus( + const authpolicy::GetUserStatusRequest& request, + GetUserStatusCallback callback) { authpolicy::ActiveDirectoryUserStatus user_status; user_status.set_password_status(password_status_); user_status.set_tgt_status(tgt_status_); authpolicy::ActiveDirectoryAccountInfo* const account_info = user_status.mutable_account_info(); - account_info->set_account_id(object_guid); + account_info->set_account_id(request.account_id()); if (!display_name_.empty()) account_info->set_display_name(display_name_); if (!given_name_.empty())
diff --git a/chromeos/dbus/fake_auth_policy_client.h b/chromeos/dbus/fake_auth_policy_client.h index e31a412..9163106 100644 --- a/chromeos/dbus/fake_auth_policy_client.h +++ b/chromeos/dbus/fake_auth_policy_client.h
@@ -42,7 +42,7 @@ // Runs |callback| with |password_status_| and |tgt_status_|. Also calls // |on_get_status_closure_| after that. - void GetUserStatus(const std::string& object_guid, + void GetUserStatus(const authpolicy::GetUserStatusRequest& request, GetUserStatusCallback callback) override; // Runs |callback| with Kerberos files.
diff --git a/chromeos/settings/cros_settings_names.cc b/chromeos/settings/cros_settings_names.cc index 687a1b5..90eec8e 100644 --- a/chromeos/settings/cros_settings_names.cc +++ b/chromeos/settings/cros_settings_names.cc
@@ -294,10 +294,6 @@ // If the string is empty or blank the system name will be used. const char kCastReceiverName[] = "cros.device.cast_receiver.name"; -// Boolean indicating whether the client needs to upload an enrollment ID -// which can be used for automatic forced re-enrollment. -const char kDeviceEnrollmentIdNeeded[] = "cros.device.enrollment_id_needed"; - // A boolean pref that indicates whether unaffiliated users are allowed to // use ARC. const char kUnaffiliatedArcAllowed[] = "cros.device.unaffiliated_arc_allowed";
diff --git a/chromeos/settings/cros_settings_names.h b/chromeos/settings/cros_settings_names.h index 275753e..2c4331e5 100644 --- a/chromeos/settings/cros_settings_names.h +++ b/chromeos/settings/cros_settings_names.h
@@ -135,8 +135,6 @@ CHROMEOS_EXPORT extern const char kCastReceiverName[]; -CHROMEOS_EXPORT extern const char kDeviceEnrollmentIdNeeded[]; - CHROMEOS_EXPORT extern const char kUnaffiliatedArcAllowed[]; CHROMEOS_EXPORT extern const char kDeviceHostnameTemplate[];
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc index 0f4b2a0..6b92be0 100644 --- a/components/autofill/core/browser/autofill_manager_unittest.cc +++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -4445,7 +4445,7 @@ // The second submission should now have data by which to infer types. autofill_manager_->set_expected_submitted_field_types(expected_types); FormSubmitted(response_data); - ASSERT_EQ(2u, personal_data_.GetProfiles().size()); + ASSERT_EQ(1u, personal_data_.GetProfiles().size()); } // Test that the form signature for an uploaded form always matches the form
diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc index 037cc62..ac0f941 100644 --- a/components/autofill/core/browser/autofill_metrics_unittest.cc +++ b/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -30,6 +30,7 @@ #include "components/autofill/core/browser/popup_item_ids.h" #include "components/autofill/core/browser/test_autofill_client.h" #include "components/autofill/core/browser/test_autofill_driver.h" +#include "components/autofill/core/browser/test_personal_data_manager.h" #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" #include "components/autofill/core/common/autofill_clock.h" #include "components/autofill/core/common/autofill_features.h" @@ -77,186 +78,6 @@ using ExpectedUkmMetrics = std::vector<std::vector<std::pair<const char*, int64_t>>>; -class TestPersonalDataManager : public PersonalDataManager { - public: - TestPersonalDataManager() - : PersonalDataManager("en-US"), autofill_enabled_(true) { - CreateTestAutofillProfiles(&web_profiles_); - } - - using PersonalDataManager::set_account_tracker; - using PersonalDataManager::set_signin_manager; - using PersonalDataManager::set_database; - using PersonalDataManager::SetPrefService; - - // Overridden to avoid a trip to the database. This should be a no-op except - // for the side-effect of logging the profile count. - void LoadProfiles() override { - pending_profiles_query_ = 123; - pending_server_profiles_query_ = 124; - { - std::vector<std::unique_ptr<AutofillProfile>> profiles; - web_profiles_.swap(profiles); - std::unique_ptr<WDTypedResult> result = std::make_unique< - WDResult<std::vector<std::unique_ptr<AutofillProfile>>>>( - AUTOFILL_PROFILES_RESULT, std::move(profiles)); - OnWebDataServiceRequestDone(pending_profiles_query_, std::move(result)); - } - { - std::vector<std::unique_ptr<AutofillProfile>> profiles; - server_profiles_.swap(profiles); - std::unique_ptr<WDTypedResult> result = std::make_unique< - WDResult<std::vector<std::unique_ptr<AutofillProfile>>>>( - AUTOFILL_PROFILES_RESULT, std::move(profiles)); - OnWebDataServiceRequestDone(pending_server_profiles_query_, - std::move(result)); - } - } - - // Overridden to avoid a trip to the database. - void LoadCreditCards() override { - pending_creditcards_query_ = 125; - pending_server_creditcards_query_ = 126; - { - std::vector<std::unique_ptr<CreditCard>> credit_cards; - local_credit_cards_.swap(credit_cards); - std::unique_ptr<WDTypedResult> result = - std::make_unique<WDResult<std::vector<std::unique_ptr<CreditCard>>>>( - AUTOFILL_CREDITCARDS_RESULT, std::move(credit_cards)); - OnWebDataServiceRequestDone(pending_creditcards_query_, - std::move(result)); - } - { - std::vector<std::unique_ptr<CreditCard>> credit_cards; - server_credit_cards_.swap(credit_cards); - std::unique_ptr<WDTypedResult> result = - std::make_unique<WDResult<std::vector<std::unique_ptr<CreditCard>>>>( - AUTOFILL_CREDITCARDS_RESULT, std::move(credit_cards)); - OnWebDataServiceRequestDone(pending_server_creditcards_query_, - std::move(result)); - } - } - - // Overridden to add potential new profiles to the |web_profiles_|. Since - // there is no database set for the test, the original method would do - // nothing. - void SetProfiles(std::vector<AutofillProfile>* profiles) override { - // Only need to copy all the profiles. This adds any new profiles created at - // form submission. - web_profiles_.clear(); - for (const auto& profile : *profiles) - web_profiles_.push_back(std::make_unique<AutofillProfile>(profile)); - } - - void set_autofill_enabled(bool autofill_enabled) { - autofill_enabled_ = autofill_enabled; - } - - // Removes all existing profiles - void ClearProfiles() { - web_profiles_.clear(); - Refresh(); - } - - // Removes all existing profiles and creates one profile. - void RecreateProfile() { - web_profiles_.clear(); - - std::unique_ptr<AutofillProfile> profile = - std::make_unique<AutofillProfile>(); - test::SetProfileInfo(profile.get(), "Elvis", "Aaron", "Presley", - "theking@gmail.com", "RCA", "3734 Elvis Presley Blvd.", - "Apt. 10", "Memphis", "Tennessee", "38116", "US", - "12345678901"); - profile->set_guid("00000000-0000-0000-0000-000000000001"); - web_profiles_.push_back(std::move(profile)); - - Refresh(); - } - - // Removes all existing credit cards and creates 0 or 1 local profiles and - // 0 or 1 server profile according to the parameters. - void RecreateCreditCards(bool include_local_credit_card, - bool include_masked_server_credit_card, - bool include_full_server_credit_card) { - local_credit_cards_.clear(); - server_credit_cards_.clear(); - if (include_local_credit_card) { - std::unique_ptr<CreditCard> credit_card = - std::make_unique<CreditCard>(test::GetCreditCard()); - credit_card->set_guid("10000000-0000-0000-0000-000000000001"); - local_credit_cards_.push_back(std::move(credit_card)); - } - if (include_masked_server_credit_card) { - std::unique_ptr<CreditCard> credit_card = std::make_unique<CreditCard>( - CreditCard::MASKED_SERVER_CARD, "server_id"); - credit_card->set_guid("10000000-0000-0000-0000-000000000002"); - credit_card->SetNetworkForMaskedCard(kDiscoverCard); - credit_card->SetNumber(ASCIIToUTF16("9424")); - server_credit_cards_.push_back(std::move(credit_card)); - } - if (include_full_server_credit_card) { - std::unique_ptr<CreditCard> credit_card = std::make_unique<CreditCard>( - CreditCard::FULL_SERVER_CARD, "server_id"); - credit_card->set_guid("10000000-0000-0000-0000-000000000003"); - server_credit_cards_.push_back(std::move(credit_card)); - } - Refresh(); - } - - // Removes all existing credit cards and creates 1 server card with a bank - // name. - void RecreateServerCreditCardsWithBankName() { - server_credit_cards_.clear(); - std::unique_ptr<CreditCard> credit_card = - std::make_unique<CreditCard>(CreditCard::FULL_SERVER_CARD, "server_id"); - test::SetCreditCardInfo(credit_card.get(), "name", "4111111111111111", "12", - "24", "1"); - credit_card->set_guid("10000000-0000-0000-0000-000000000003"); - credit_card->set_bank_name("Chase"); - server_credit_cards_.push_back(std::move(credit_card)); - Refresh(); - } - - bool IsAutofillEnabled() const override { return autofill_enabled_; } - - void CreateAmbiguousProfiles() { - web_profiles_.clear(); - CreateTestAutofillProfiles(&web_profiles_); - - auto profile = std::make_unique<AutofillProfile>(); - test::SetProfileInfo(profile.get(), "John", "Decca", "Public", - "john@gmail.com", "Company", "123 Main St.", "unit 7", - "Springfield", "Texas", "79401", "US", "2345678901"); - profile->set_guid("00000000-0000-0000-0000-000000000003"); - web_profiles_.push_back(std::move(profile)); - Refresh(); - } - - private: - void CreateTestAutofillProfiles( - std::vector<std::unique_ptr<AutofillProfile>>* profiles) { - std::unique_ptr<AutofillProfile> profile = - std::make_unique<AutofillProfile>(); - test::SetProfileInfo(profile.get(), "Elvis", "Aaron", "Presley", - "theking@gmail.com", "RCA", "3734 Elvis Presley Blvd.", - "Apt. 10", "Memphis", "Tennessee", "38116", "US", - "12345678901"); - profile->set_guid("00000000-0000-0000-0000-000000000001"); - profiles->push_back(std::move(profile)); - profile = std::make_unique<AutofillProfile>(); - test::SetProfileInfo(profile.get(), "Charles", "Hardin", "Holley", - "buddy@gmail.com", "Decca", "123 Apple St.", "unit 6", - "Lubbock", "Texas", "79401", "US", "2345678901"); - profile->set_guid("00000000-0000-0000-0000-000000000002"); - profiles->push_back(std::move(profile)); - } - - bool autofill_enabled_; - - DISALLOW_COPY_AND_ASSIGN(TestPersonalDataManager); -}; - class TestFormStructure : public FormStructure { public: explicit TestFormStructure(const FormData& form) : FormStructure(form) {} @@ -486,6 +307,20 @@ protected: void EnableWalletSync(); + void CreateAmbiguousProfiles(); + + // Removes all existing profiles and creates one profile. + void RecreateProfile(); + + // Removes all existing credit cards and creates 0 or 1 local profiles and + // 0 or 1 server profile according to the parameters. + void RecreateCreditCards(bool include_local_credit_card, + bool include_masked_server_credit_card, + bool include_full_server_credit_card); + + // Removes all existing credit cards and creates 1 server card with a bank + // name. + void RecreateServerCreditCardsWithBankName(); base::test::ScopedTaskEnvironment scoped_task_environment_; ukm::TestAutoSetUkmRecorder test_ukm_recorder_; @@ -498,6 +333,9 @@ std::unique_ptr<TestPersonalDataManager> personal_data_; std::unique_ptr<AutofillExternalDelegate> external_delegate_; base::test::ScopedFeatureList scoped_feature_list_; + + private: + void CreateTestAutofillProfiles(); }; AutofillMetricsTest::~AutofillMetricsTest() { @@ -512,7 +350,7 @@ // Ensure Mac OS X does not pop up a modal dialog for the Address Book. test::DisableSystemServices(autofill_client_.GetPrefs()); - // Setup identity services. + // Set up identity services. signin_client_.reset(new TestSigninClient(autofill_client_.GetPrefs())); account_tracker_.reset(new AccountTrackerService()); account_tracker_->Initialize(signin_client_.get()); @@ -533,6 +371,9 @@ external_delegate_.reset(new AutofillExternalDelegate( autofill_manager_.get(), autofill_driver_.get())); autofill_manager_->SetExternalDelegate(external_delegate_.get()); + + // Initialize the TestPersonalDataManager with some default data. + CreateTestAutofillProfiles(); } void AutofillMetricsTest::TearDown() { @@ -554,6 +395,89 @@ signin_manager_->SetAuthenticatedAccountInfo("12345", "syncuser@example.com"); } +void AutofillMetricsTest::CreateAmbiguousProfiles() { + personal_data_->ClearProfiles(); + CreateTestAutofillProfiles(); + + AutofillProfile profile; + test::SetProfileInfo(&profile, "John", "Decca", "Public", "john@gmail.com", + "Company", "123 Main St.", "unit 7", "Springfield", + "Texas", "79401", "US", "2345678901"); + profile.set_guid("00000000-0000-0000-0000-000000000003"); + personal_data_->AddProfile(profile); + personal_data_->Refresh(); +} + +void AutofillMetricsTest::RecreateProfile() { + personal_data_->ClearProfiles(); + + AutofillProfile profile; + test::SetProfileInfo(&profile, "Elvis", "Aaron", "Presley", + "theking@gmail.com", "RCA", "3734 Elvis Presley Blvd.", + "Apt. 10", "Memphis", "Tennessee", "38116", "US", + "12345678901"); + profile.set_guid("00000000-0000-0000-0000-000000000001"); + personal_data_->AddProfile(profile); + personal_data_->Refresh(); +} + +void AutofillMetricsTest::RecreateCreditCards( + bool include_local_credit_card, + bool include_masked_server_credit_card, + bool include_full_server_credit_card) { + personal_data_->ClearCreditCards(); + if (include_local_credit_card) { + CreditCard local_credit_card; + test::SetCreditCardInfo(&local_credit_card, "Test User", + "4111111111111111" /* Visa */, "11", "2022", "1"); + local_credit_card.set_guid("10000000-0000-0000-0000-000000000001"); + personal_data_->AddCreditCard(local_credit_card); + } + if (include_masked_server_credit_card) { + CreditCard masked_server_credit_card(CreditCard::MASKED_SERVER_CARD, + "server_id"); + masked_server_credit_card.set_guid("10000000-0000-0000-0000-000000000002"); + masked_server_credit_card.SetNetworkForMaskedCard(kDiscoverCard); + masked_server_credit_card.SetNumber(ASCIIToUTF16("9424")); + personal_data_->AddServerCreditCard(masked_server_credit_card); + } + if (include_full_server_credit_card) { + CreditCard full_server_credit_card(CreditCard::FULL_SERVER_CARD, + "server_id"); + full_server_credit_card.set_guid("10000000-0000-0000-0000-000000000003"); + personal_data_->AddFullServerCreditCard(full_server_credit_card); + } + personal_data_->Refresh(); +} + +void AutofillMetricsTest::RecreateServerCreditCardsWithBankName() { + personal_data_->ClearCreditCards(); + CreditCard credit_card(CreditCard::FULL_SERVER_CARD, "server_id"); + test::SetCreditCardInfo(&credit_card, "name", "4111111111111111", "12", "24", + "1"); + credit_card.set_guid("10000000-0000-0000-0000-000000000003"); + credit_card.set_bank_name("Chase"); + personal_data_->AddFullServerCreditCard(credit_card); + personal_data_->Refresh(); +} + +void AutofillMetricsTest::CreateTestAutofillProfiles() { + AutofillProfile profile1; + test::SetProfileInfo(&profile1, "Elvis", "Aaron", "Presley", + "theking@gmail.com", "RCA", "3734 Elvis Presley Blvd.", + "Apt. 10", "Memphis", "Tennessee", "38116", "US", + "12345678901"); + profile1.set_guid("00000000-0000-0000-0000-000000000001"); + personal_data_->AddProfile(profile1); + + AutofillProfile profile2; + test::SetProfileInfo(&profile2, "Charles", "Hardin", "Holley", + "buddy@gmail.com", "Decca", "123 Apple St.", "unit 6", + "Lubbock", "Texas", "79401", "US", "2345678901"); + profile2.set_guid("00000000-0000-0000-0000-000000000002"); + personal_data_->AddProfile(profile2); +} + // Test that we log quality metrics appropriately. TEST_F(AutofillMetricsTest, QualityMetrics) { // Set up our form data. @@ -1163,7 +1087,7 @@ case AMBIGUOUS_TYPE: // This occurs as both a company name and a middle name once ambiguous // profiles are created. - personal_data_->CreateAmbiguousProfiles(); + CreateAmbiguousProfiles(); return "Decca"; default: @@ -2571,10 +2495,9 @@ // The metric should be logged when the credit cards are first loaded. { base::HistogramTester histogram_tester; - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - false /* include_masked_server_credit_card */, - false /* include_full_server_credit_card */); + RecreateCreditCards(true /* include_local_credit_card */, + false /* include_masked_server_credit_card */, + false /* include_full_server_credit_card */); histogram_tester.ExpectUniqueSample("Autofill.StoredLocalCreditCardCount", 1, 1); } @@ -2582,10 +2505,9 @@ // The metric should only be logged once. { base::HistogramTester histogram_tester; - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - false /* include_masked_server_credit_card */, - false /* include_full_server_credit_card */); + RecreateCreditCards(true /* include_local_credit_card */, + false /* include_masked_server_credit_card */, + false /* include_full_server_credit_card */); histogram_tester.ExpectTotalCount("Autofill.StoredLocalCreditCardCount", 0); } } @@ -2595,10 +2517,9 @@ // The metrics should be logged when the credit cards are first loaded. { base::HistogramTester histogram_tester; - personal_data_->RecreateCreditCards( - false /* include_local_credit_card */, - true /* include_masked_server_credit_card */, - false /* include_full_server_credit_card */); + RecreateCreditCards(false /* include_local_credit_card */, + true /* include_masked_server_credit_card */, + false /* include_full_server_credit_card */); histogram_tester.ExpectUniqueSample( "Autofill.StoredServerCreditCardCount.Masked", 1, 1); } @@ -2606,10 +2527,9 @@ // The metrics should only be logged once. { base::HistogramTester histogram_tester; - personal_data_->RecreateCreditCards( - false /* include_local_credit_card */, - true /* include_masked_server_credit_card */, - true /* include_full_server_credit_card */); + RecreateCreditCards(false /* include_local_credit_card */, + true /* include_masked_server_credit_card */, + true /* include_full_server_credit_card */); histogram_tester.ExpectTotalCount( "Autofill.StoredServerCreditCardCount.Masked", 0); } @@ -2620,10 +2540,9 @@ // The metrics should be logged when the credit cards are first loaded. { base::HistogramTester histogram_tester; - personal_data_->RecreateCreditCards( - false /* include_local_credit_card */, - false /* include_masked_server_credit_card */, - true /* include_full_server_credit_card */); + RecreateCreditCards(false /* include_local_credit_card */, + false /* include_masked_server_credit_card */, + true /* include_full_server_credit_card */); histogram_tester.ExpectUniqueSample( "Autofill.StoredServerCreditCardCount.Unmasked", 1, 1); } @@ -2631,10 +2550,9 @@ // The metrics should only be logged once. { base::HistogramTester histogram_tester; - personal_data_->RecreateCreditCards( - false /* include_local_credit_card */, - false /* include_masked_server_credit_card */, - true /* include_full_server_credit_card */); + RecreateCreditCards(false /* include_local_credit_card */, + false /* include_masked_server_credit_card */, + true /* include_full_server_credit_card */); histogram_tester.ExpectTotalCount( "Autofill.StoredServerCreditCardCount.Unmasked", 0); } @@ -2643,7 +2561,7 @@ // Test that we correctly log when Autofill is enabled. TEST_F(AutofillMetricsTest, AutofillIsEnabledAtStartup) { base::HistogramTester histogram_tester; - personal_data_->set_autofill_enabled(true); + personal_data_->SetAutofillEnabled(true); personal_data_->Init(autofill_client_.GetDatabase(), autofill_client_.GetPrefs(), account_tracker_.get(), signin_manager_.get(), false); @@ -2653,7 +2571,7 @@ // Test that we correctly log when Autofill is disabled. TEST_F(AutofillMetricsTest, AutofillIsDisabledAtStartup) { base::HistogramTester histogram_tester; - personal_data_->set_autofill_enabled(false); + personal_data_->SetAutofillEnabled(false); personal_data_->Init(autofill_client_.GetDatabase(), autofill_client_.GetPrefs(), account_tracker_.get(), signin_manager_.get(), false); @@ -2730,10 +2648,9 @@ // Test that the credit card checkout flow user actions are correctly logged. TEST_F(AutofillMetricsTest, CreditCardCheckoutFlowUserActions) { - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - false /* include_masked_server_credit_card */, - false /* include_full_server_credit_card */); + RecreateCreditCards(true /* include_local_credit_card */, + false /* include_masked_server_credit_card */, + false /* include_full_server_credit_card */); // Set up our form data. FormData form; @@ -2847,7 +2764,7 @@ // Test that the profile checkout flow user actions are correctly logged. TEST_F(AutofillMetricsTest, ProfileCheckoutFlowUserActions) { // Create a profile. - personal_data_->RecreateProfile(); + RecreateProfile(); // Set up our form data. FormData form; @@ -2962,10 +2879,9 @@ // Tests that the Autofill_PolledCreditCardSuggestions user action is only // logged once if the field is queried repeatedly. TEST_F(AutofillMetricsTest, PolledCreditCardSuggestions_DebounceLogs) { - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - false /* include_masked_server_credit_card */, - false /* include_full_server_credit_card */); + 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; @@ -3018,10 +2934,9 @@ // 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 */); + 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; @@ -3083,7 +2998,7 @@ // Tests that the Autofill_PolledProfileSuggestions user action is only logged // once if the field is queried repeatedly. TEST_F(AutofillMetricsTest, PolledProfileSuggestions_DebounceLogs) { - personal_data_->RecreateProfile(); + RecreateProfile(); // Set up the form data. FormData form; @@ -3275,7 +3190,7 @@ } // Recreate server cards with bank names. - personal_data_->RecreateServerCreditCardsWithBankName(); + RecreateServerCreditCardsWithBankName(); // Reset the autofill manager state. autofill_manager_->Reset(); @@ -3327,10 +3242,9 @@ TEST_F(AutofillMetricsTest, CreditCardSelectedFormEvents) { EnableWalletSync(); // Creating all kinds of cards. - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - true /* include_masked_server_credit_card */, - true /* include_full_server_credit_card */); + RecreateCreditCards(true /* include_local_credit_card */, + true /* include_masked_server_credit_card */, + true /* include_full_server_credit_card */); // Set up our form data. FormData form; form.name = ASCIIToUTF16("TestForm"); @@ -3400,10 +3314,9 @@ // Test that we log filled form events for credit cards. TEST_F(AutofillMetricsTest, CreditCardFilledFormEvents) { // Creating all kinds of cards. - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - true /* include_masked_server_credit_card */, - true /* include_full_server_credit_card */); + RecreateCreditCards(true /* include_local_credit_card */, + true /* include_masked_server_credit_card */, + true /* include_full_server_credit_card */); // Set up our form data. FormData form; form.name = ASCIIToUTF16("TestForm"); @@ -3469,10 +3382,9 @@ // Recreating cards as the previous test should have upgraded the masked // card to a full card. - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - true /* include_masked_server_credit_card */, - true /* include_full_server_credit_card */); + RecreateCreditCards(true /* include_local_credit_card */, + true /* include_masked_server_credit_card */, + true /* include_full_server_credit_card */); // Reset the autofill manager state. autofill_manager_->Reset(); @@ -3522,7 +3434,7 @@ } // Recreate server cards with bank names. - personal_data_->RecreateServerCreditCardsWithBankName(); + RecreateServerCreditCardsWithBankName(); // Reset the autofill manager state. autofill_manager_->Reset(); @@ -3572,10 +3484,9 @@ TEST_F(AutofillMetricsTest, CreditCardGetRealPanDuration) { EnableWalletSync(); // Creating masked card - personal_data_->RecreateCreditCards( - false /* include_local_credit_card */, - true /* include_masked_server_credit_card */, - false /* include_full_server_credit_card */); + RecreateCreditCards(false /* include_local_credit_card */, + true /* include_masked_server_credit_card */, + false /* include_full_server_credit_card */); // Set up our form data. FormData form; form.name = ASCIIToUTF16("TestForm"); @@ -3620,10 +3531,9 @@ autofill_manager_->Reset(); autofill_manager_->AddSeenForm(form, field_types, field_types); // Creating masked card - personal_data_->RecreateCreditCards( - false /* include_local_credit_card */, - true /* include_masked_server_credit_card */, - false /* include_full_server_credit_card */); + RecreateCreditCards(false /* include_local_credit_card */, + true /* include_masked_server_credit_card */, + false /* include_full_server_credit_card */); { // Simulating filling a masked card server suggestion. @@ -3646,10 +3556,9 @@ CreditCardSubmittedWithoutSelectingSuggestionsNoCard) { EnableWalletSync(); // Create a local card for testing, card number is 4111111111111111. - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - false /* include_masked_server_credit_card */, - false /* include_full_server_credit_card */); + RecreateCreditCards(true /* include_local_credit_card */, + false /* include_masked_server_credit_card */, + false /* include_full_server_credit_card */); // Set up our form data. FormData form; @@ -3690,10 +3599,9 @@ CreditCardSubmittedWithoutSelectingSuggestionsWrongSizeCard) { EnableWalletSync(); // Create a local card for testing, card number is 4111111111111111. - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - false /* include_masked_server_credit_card */, - false /* include_full_server_credit_card */); + RecreateCreditCards(true /* include_local_credit_card */, + false /* include_masked_server_credit_card */, + false /* include_full_server_credit_card */); // Set up our form data. FormData form; @@ -3733,10 +3641,9 @@ CreditCardSubmittedWithoutSelectingSuggestionsFailLuhnCheckCard) { EnableWalletSync(); // Create a local card for testing, card number is 4111111111111111. - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - false /* include_masked_server_credit_card */, - false /* include_full_server_credit_card */); + RecreateCreditCards(true /* include_local_credit_card */, + false /* include_masked_server_credit_card */, + false /* include_full_server_credit_card */); // Set up our form data. FormData form; @@ -3777,10 +3684,9 @@ CreditCardSubmittedWithoutSelectingSuggestionsUnknownCard) { EnableWalletSync(); // Create a local card for testing, card number is 4111111111111111. - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - false /* include_masked_server_credit_card */, - false /* include_full_server_credit_card */); + RecreateCreditCards(true /* include_local_credit_card */, + false /* include_masked_server_credit_card */, + false /* include_full_server_credit_card */); // Set up our form data. FormData form; @@ -3823,10 +3729,9 @@ CreditCardSubmittedWithoutSelectingSuggestionsKnownCard) { EnableWalletSync(); // Create a local card for testing, card number is 4111111111111111. - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - false /* include_masked_server_credit_card */, - false /* include_full_server_credit_card */); + RecreateCreditCards(true /* include_local_credit_card */, + false /* include_masked_server_credit_card */, + false /* include_full_server_credit_card */); // Set up our form data. FormData form; @@ -3869,10 +3774,9 @@ ShouldNotLogSubmitWithoutSelectingSuggestionsIfSuggestionFilled) { EnableWalletSync(); // Create a local card for testing, card number is 4111111111111111. - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - false /* include_masked_server_credit_card */, - false /* include_full_server_credit_card */); + RecreateCreditCards(true /* include_local_credit_card */, + false /* include_masked_server_credit_card */, + false /* include_full_server_credit_card */); // Set up our form data. FormData form; @@ -3928,7 +3832,7 @@ TEST_F(AutofillMetricsTest, ShouldNotLogFormEventNoCardForAddressForm) { EnableWalletSync(); // Create a profile. - personal_data_->RecreateProfile(); + RecreateProfile(); // Set up our form data. FormData form; form.name = ASCIIToUTF16("TestForm"); @@ -3968,10 +3872,9 @@ TEST_F(AutofillMetricsTest, CreditCardSubmittedFormEvents) { EnableWalletSync(); // Creating all kinds of cards. - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - true /* include_masked_server_credit_card */, - true /* include_full_server_credit_card */); + RecreateCreditCards(true /* include_local_credit_card */, + true /* include_masked_server_credit_card */, + true /* include_full_server_credit_card */); // Set up our form data. FormData form; form.name = ASCIIToUTF16("TestForm"); @@ -4184,10 +4087,9 @@ // Recreating cards as the previous test should have upgraded the masked // card to a full card. - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - true /* include_masked_server_credit_card */, - true /* include_full_server_credit_card */); + RecreateCreditCards(true /* include_local_credit_card */, + true /* include_masked_server_credit_card */, + true /* include_full_server_credit_card */); // Reset the autofill manager state. autofill_manager_->Reset(); @@ -4317,10 +4219,9 @@ TEST_F(AutofillMetricsTest, CreditCardWillSubmitFormEvents) { EnableWalletSync(); // Creating all kinds of cards. - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - true /* include_masked_server_credit_card */, - true /* include_full_server_credit_card */); + RecreateCreditCards(true /* include_local_credit_card */, + true /* include_masked_server_credit_card */, + true /* include_full_server_credit_card */); // Set up our form data. FormData form; form.name = ASCIIToUTF16("TestForm"); @@ -4444,10 +4345,9 @@ // Recreating cards as the previous test should have upgraded the masked // card to a full card. - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - true /* include_masked_server_credit_card */, - true /* include_full_server_credit_card */); + RecreateCreditCards(true /* include_local_credit_card */, + true /* include_masked_server_credit_card */, + true /* include_full_server_credit_card */); // Reset the autofill manager state. autofill_manager_->Reset(); @@ -4596,7 +4496,7 @@ TEST_F(AutofillMetricsTest, AddressShownFormEvents) { EnableWalletSync(); // Create a profile. - personal_data_->RecreateProfile(); + RecreateProfile(); // Set up our form data. FormData form; form.name = ASCIIToUTF16("TestForm"); @@ -4687,7 +4587,7 @@ TEST_F(AutofillMetricsTest, AddressFilledFormEvents) { EnableWalletSync(); // Create a profile. - personal_data_->RecreateProfile(); + RecreateProfile(); // Set up our form data. FormData form; form.name = ASCIIToUTF16("TestForm"); @@ -4754,7 +4654,7 @@ TEST_F(AutofillMetricsTest, AddressSubmittedFormEvents) { EnableWalletSync(); // Create a profile. - personal_data_->RecreateProfile(); + RecreateProfile(); // Set up our form data. FormData form; form.name = ASCIIToUTF16("TestForm"); @@ -4956,7 +4856,7 @@ TEST_F(AutofillMetricsTest, AddressWillSubmitFormEvents) { EnableWalletSync(); // Create a profile. - personal_data_->RecreateProfile(); + RecreateProfile(); // Set up our form data. FormData form; form.name = ASCIIToUTF16("TestForm"); @@ -5153,10 +5053,9 @@ // Simulate having seen this form on page load. // |form_structure| will be owned by |autofill_manager_|. autofill_manager_->AddSeenForm(form, field_types, field_types); - personal_data_->RecreateCreditCards( - false /* include_local_credit_card */, - false /* include_masked_server_credit_card */, - false /* include_full_server_credit_card */); + RecreateCreditCards(false /* include_local_credit_card */, + false /* include_masked_server_credit_card */, + false /* include_full_server_credit_card */); { // Simulate activating the autofill popup for the credit card field. @@ -5170,10 +5069,9 @@ // Reset the autofill manager state. autofill_manager_->Reset(); autofill_manager_->AddSeenForm(form, field_types, field_types); - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - false /* include_masked_server_credit_card */, - false /* include_full_server_credit_card */); + RecreateCreditCards(true /* include_local_credit_card */, + false /* include_masked_server_credit_card */, + false /* include_full_server_credit_card */); { // Simulate activating the autofill popup for the credit card field. @@ -5187,10 +5085,9 @@ // Reset the autofill manager state. autofill_manager_->Reset(); autofill_manager_->AddSeenForm(form, field_types, field_types); - personal_data_->RecreateCreditCards( - false /* include_local_credit_card */, - true /* include_masked_server_credit_card */, - false /* include_full_server_credit_card */); + RecreateCreditCards(false /* include_local_credit_card */, + true /* include_masked_server_credit_card */, + false /* include_full_server_credit_card */); { // Simulate activating the autofill popup for the credit card field. @@ -5204,10 +5101,9 @@ // Reset the autofill manager state. autofill_manager_->Reset(); autofill_manager_->AddSeenForm(form, field_types, field_types); - personal_data_->RecreateCreditCards( - false /* include_local_credit_card */, - false /* include_masked_server_credit_card */, - true /* include_full_server_credit_card */); + RecreateCreditCards(false /* include_local_credit_card */, + false /* include_masked_server_credit_card */, + true /* include_full_server_credit_card */); { // Simulate activating the autofill popup for the credit card field. @@ -5221,10 +5117,9 @@ // Reset the autofill manager state. autofill_manager_->Reset(); autofill_manager_->AddSeenForm(form, field_types, field_types); - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - false /* include_masked_server_credit_card */, - true /* include_full_server_credit_card */); + RecreateCreditCards(true /* include_local_credit_card */, + false /* include_masked_server_credit_card */, + true /* include_full_server_credit_card */); { // Simulate activating the autofill popup for the credit card field. @@ -5277,7 +5172,7 @@ // Reset the autofill manager state. autofill_manager_->Reset(); autofill_manager_->AddSeenForm(form, field_types, field_types); - personal_data_->RecreateProfile(); + RecreateProfile(); { // Simulate activating the autofill popup for the street field. @@ -5725,10 +5620,9 @@ // Verify that we correctly log user happiness metrics dealing with form // interaction. TEST_F(AutofillMetricsTest, UserHappinessFormInteraction_CreditCardForm) { - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - false /* include_masked_server_credit_card */, - false /* include_full_server_credit_card */); + RecreateCreditCards(true /* include_local_credit_card */, + false /* include_masked_server_credit_card */, + false /* include_full_server_credit_card */); // Load a fillable form. FormData form; @@ -6757,10 +6651,9 @@ // Tests that credit card form submissions are logged specially when the form is // on a non-secure page. TEST_F(AutofillMetricsTest, NonsecureCreditCardForm) { - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - false /* include_masked_server_credit_card */, - false /* include_full_server_credit_card */); + RecreateCreditCards(true /* include_local_credit_card */, + false /* include_masked_server_credit_card */, + false /* include_full_server_credit_card */); // Set up our form data. FormData form; @@ -6815,10 +6708,9 @@ // form is *not* on a non-secure page. TEST_F(AutofillMetricsTest, NonsecureCreditCardFormMetricsNotRecordedOnSecurePage) { - personal_data_->RecreateCreditCards( - true /* include_local_credit_card */, - false /* include_masked_server_credit_card */, - false /* include_full_server_credit_card */); + RecreateCreditCards(true /* include_local_credit_card */, + false /* include_masked_server_credit_card */, + false /* include_full_server_credit_card */); // Set up our form data. FormData form;
diff --git a/components/autofill/core/browser/credit_card_save_manager_unittest.cc b/components/autofill/core/browser/credit_card_save_manager_unittest.cc index 9451005..8fbad228 100644 --- a/components/autofill/core/browser/credit_card_save_manager_unittest.cc +++ b/components/autofill/core/browser/credit_card_save_manager_unittest.cc
@@ -1539,18 +1539,21 @@ personal_data_.ClearProfiles(); credit_card_save_manager_->set_credit_card_upload_enabled(true); - // Create, fill and submit two address forms with different zip codes. - FormData address_form1, address_form2; - test::CreateTestAddressFormData(&address_form1); - test::CreateTestAddressFormData(&address_form2); + // Create two separate profiles with different zip codes. Must directly add + // instead of submitting a form, because they're deduped on form submit. + AutofillProfile profile1; + profile1.set_guid("00000000-0000-0000-0000-000000000001"); + profile1.SetInfo(NAME_FULL, ASCIIToUTF16("Flo Master"), "en-US"); + profile1.SetInfo(ADDRESS_HOME_ZIP, ASCIIToUTF16("H3B2Y5"), "en-US"); + profile1.SetInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("CA"), "en-US"); + personal_data_.AddProfile(profile1); - FormsSeen({address_form1, address_form2}); - - ManuallyFillAddressForm("Flo", "Master", "H3B2Y5", "CA", &address_form1); - FormSubmitted(address_form1); - - ManuallyFillAddressForm("Flo", "Master", "h3b 2y5", "CA", &address_form2); - FormSubmitted(address_form2); + AutofillProfile profile2; + profile2.set_guid("00000000-0000-0000-0000-000000000002"); + profile2.SetInfo(NAME_FULL, ASCIIToUTF16("Flo Master"), "en-US"); + profile2.SetInfo(ADDRESS_HOME_ZIP, ASCIIToUTF16("h3b 2y5"), "en-US"); + profile2.SetInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("CA"), "en-US"); + personal_data_.AddProfile(profile2); // Set up our credit card form data. FormData credit_card_form;
diff --git a/components/autofill/core/browser/personal_data_manager.h b/components/autofill/core/browser/personal_data_manager.h index 2d072c8..02855477 100644 --- a/components/autofill/core/browser/personal_data_manager.h +++ b/components/autofill/core/browser/personal_data_manager.h
@@ -357,6 +357,7 @@ friend class autofill::AutofillInteractiveTest; friend class autofill::PersonalDataManagerFactory; + friend class AutofillMetricsTest; friend class FormDataImporterTest; friend class PersonalDataManagerTest; friend class PersonalDataManagerTestBase;
diff --git a/components/autofill/core/browser/test_personal_data_manager.cc b/components/autofill/core/browser/test_personal_data_manager.cc index 65cb6fe..2a8966c 100644 --- a/components/autofill/core/browser/test_personal_data_manager.cc +++ b/components/autofill/core/browser/test_personal_data_manager.cc
@@ -26,8 +26,7 @@ std::string TestPersonalDataManager::SaveImportedProfile( const AutofillProfile& imported_profile) { num_times_save_imported_profile_called_++; - AddProfile(imported_profile); - return imported_profile.guid(); + return PersonalDataManager::SaveImportedProfile(imported_profile); } std::string TestPersonalDataManager::SaveImportedCreditCard( @@ -109,6 +108,68 @@ return default_country_code_; } +void TestPersonalDataManager::SetProfiles( + std::vector<AutofillProfile>* profiles) { + // Copy all the profiles. Called by functions like + // PersonalDataManager::SaveImportedProfile, which impact metrics. + ClearProfiles(); + for (const auto& profile : *profiles) + AddProfile(profile); +} + +void TestPersonalDataManager::LoadProfiles() { + // Overridden to avoid a trip to the database. This should be a no-op except + // for the side-effect of logging the profile count. + pending_profiles_query_ = 123; + pending_server_profiles_query_ = 124; + { + std::vector<std::unique_ptr<AutofillProfile>> profiles; + web_profiles_.swap(profiles); + std::unique_ptr<WDTypedResult> result = std::make_unique< + WDResult<std::vector<std::unique_ptr<AutofillProfile>>>>( + AUTOFILL_PROFILES_RESULT, std::move(profiles)); + OnWebDataServiceRequestDone(pending_profiles_query_, std::move(result)); + } + { + std::vector<std::unique_ptr<AutofillProfile>> profiles; + server_profiles_.swap(profiles); + std::unique_ptr<WDTypedResult> result = std::make_unique< + WDResult<std::vector<std::unique_ptr<AutofillProfile>>>>( + AUTOFILL_PROFILES_RESULT, std::move(profiles)); + OnWebDataServiceRequestDone(pending_server_profiles_query_, + std::move(result)); + } +} + +void TestPersonalDataManager::LoadCreditCards() { + // Overridden to avoid a trip to the database. + pending_creditcards_query_ = 125; + pending_server_creditcards_query_ = 126; + { + std::vector<std::unique_ptr<CreditCard>> credit_cards; + local_credit_cards_.swap(credit_cards); + std::unique_ptr<WDTypedResult> result = + std::make_unique<WDResult<std::vector<std::unique_ptr<CreditCard>>>>( + AUTOFILL_CREDITCARDS_RESULT, std::move(credit_cards)); + OnWebDataServiceRequestDone(pending_creditcards_query_, std::move(result)); + } + { + std::vector<std::unique_ptr<CreditCard>> credit_cards; + server_credit_cards_.swap(credit_cards); + std::unique_ptr<WDTypedResult> result = + std::make_unique<WDResult<std::vector<std::unique_ptr<CreditCard>>>>( + AUTOFILL_CREDITCARDS_RESULT, std::move(credit_cards)); + OnWebDataServiceRequestDone(pending_server_creditcards_query_, + std::move(result)); + } +} + +bool TestPersonalDataManager::IsAutofillEnabled() const { + // Return the value of autofill_enabled_ if it has been set, otherwise fall + // back to the normal behavior of checking the pref_service. + return autofill_enabled_.value_or(PersonalDataManager::IsAutofillEnabled()); +} + std::string TestPersonalDataManager::CountryCodeForCurrentTimezone() const { return timezone_country_code_;
diff --git a/components/autofill/core/browser/test_personal_data_manager.h b/components/autofill/core/browser/test_personal_data_manager.h index 8c481e5..65a2eb2 100644 --- a/components/autofill/core/browser/test_personal_data_manager.h +++ b/components/autofill/core/browser/test_personal_data_manager.h
@@ -7,6 +7,7 @@ #include <vector> +#include "base/optional.h" #include "components/autofill/core/browser/autofill_profile.h" #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/personal_data_manager.h" @@ -38,6 +39,10 @@ std::vector<AutofillProfile*> GetProfiles() const override; std::vector<CreditCard*> GetCreditCards() const override; const std::string& GetDefaultCountryCodeForNewAddress() const override; + void SetProfiles(std::vector<AutofillProfile>* profiles) override; + void LoadProfiles() override; + void LoadCreditCards() override; + bool IsAutofillEnabled() const override; std::string CountryCodeForCurrentTimezone() const override; // Unique to TestPersonalDataManager: @@ -69,10 +74,15 @@ return num_times_save_imported_profile_called_; } + void SetAutofillEnabled(bool autofill_enabled) { + autofill_enabled_ = autofill_enabled; + } + private: std::string timezone_country_code_; std::string default_country_code_; int num_times_save_imported_profile_called_ = 0; + base::Optional<bool> autofill_enabled_; DISALLOW_COPY_AND_ASSIGN(TestPersonalDataManager); };
diff --git a/components/autofill/ios/browser/autofill_agent.mm b/components/autofill/ios/browser/autofill_agent.mm index 0817635..28960d45 100644 --- a/components/autofill/ios/browser/autofill_agent.mm +++ b/components/autofill/ios/browser/autofill_agent.mm
@@ -574,11 +574,6 @@ } web::URLVerificationTrustLevel trustLevel; const GURL pageURL(webState->GetCurrentURL(&trustLevel)); - if (trustLevel != web::URLVerificationTrustLevel::kAbsolute) { - DLOG(WARNING) << "Suggestions not offered on untrusted page"; - completion(NO); - return; - } // Once the active form and field are extracted, send a query to the // AutofillManager for suggestions.
diff --git a/components/cloud_devices/common/printer_description.cc b/components/cloud_devices/common/printer_description.cc index 918a183e..7f3ae78 100644 --- a/components/cloud_devices/common/printer_description.cc +++ b/components/cloud_devices/common/printer_description.cc
@@ -67,6 +67,7 @@ const char kPageRangeEnd[] = "end"; const char kPageRangeStart[] = "start"; +const char kPwgRasterDocumentTypeSupported[] = "document_type_supported"; const char kPwgRasterDocumentSheetBack[] = "document_sheet_back"; const char kPwgRasterReverseOrderStreaming[] = "reverse_order_streaming"; const char kPwgRasterRotateAllPages[] = "rotate_all_pages"; @@ -95,6 +96,9 @@ const char kTypeOrientationLandscape[] = "LANDSCAPE"; const char kTypeOrientationPortrait[] = "PORTRAIT"; +const char kTypeDocumentSupportedTypeSRGB8[] = "SRGB_8"; +const char kTypeDocumentSupportedTypeSGRAY8[] = "SGRAY_8"; + const char kTypeDocumentSheetBackNormal[] = "NORMAL"; const char kTypeDocumentSheetBackRotated[] = "ROTATED"; const char kTypeDocumentSheetBackManualTumble[] = "MANUAL_TUMBLE"; @@ -391,6 +395,8 @@ rotate_all_pages(false) { } +PwgRasterConfig::~PwgRasterConfig() {} + Color::Color() : type(AUTO_COLOR) { } @@ -564,6 +570,24 @@ } } + const base::Value* document_types_supported = + dict.FindKey(kPwgRasterDocumentTypeSupported); + if (document_types_supported) { + if (!document_types_supported->is_list()) + return false; + + for (const auto& type : document_types_supported->GetList()) { + if (!type.is_string()) + return false; + + std::string type_str = type.GetString(); + if (type_str == kTypeDocumentSupportedTypeSRGB8) + option_out.document_types_supported.push_back(SRGB_8); + else if (type_str == kTypeDocumentSupportedTypeSGRAY8) + option_out.document_types_supported.push_back(SGRAY_8); + } + } + dict.GetBoolean(kPwgRasterReverseOrderStreaming, &option_out.reverse_order_streaming); dict.GetBoolean(kPwgRasterRotateAllPages, &option_out.rotate_all_pages); @@ -576,6 +600,24 @@ kPwgRasterDocumentSheetBack, TypeToString(kDocumentSheetBackNames, option.document_sheet_back)); + if (!option.document_types_supported.empty()) { + base::Value::ListStorage supported_list; + for (const auto& type : option.document_types_supported) { + switch (type) { + case SRGB_8: + supported_list.push_back( + base::Value(kTypeDocumentSupportedTypeSRGB8)); + break; + case SGRAY_8: + supported_list.push_back( + base::Value(kTypeDocumentSupportedTypeSGRAY8)); + break; + } + } + dict->SetKey(kPwgRasterDocumentTypeSupported, + base::Value(supported_list)); + } + if (option.reverse_order_streaming) { dict->SetBoolean(kPwgRasterReverseOrderStreaming, option.reverse_order_streaming);
diff --git a/components/cloud_devices/common/printer_description.h b/components/cloud_devices/common/printer_description.h index 3c5a5d81..344075f8 100644 --- a/components/cloud_devices/common/printer_description.h +++ b/components/cloud_devices/common/printer_description.h
@@ -24,9 +24,16 @@ enum DocumentSheetBack { NORMAL, ROTATED, MANUAL_TUMBLE, FLIPPED }; +enum PwgDocumentTypeSupported { + SGRAY_8 = 22, + SRGB_8 = 23, +}; + struct PwgRasterConfig { PwgRasterConfig(); + ~PwgRasterConfig(); + std::vector<PwgDocumentTypeSupported> document_types_supported; DocumentSheetBack document_sheet_back; bool reverse_order_streaming; bool rotate_all_pages;
diff --git a/components/cloud_devices/common/printer_description_unittest.cc b/components/cloud_devices/common/printer_description_unittest.cc index d514239..a61825f 100644 --- a/components/cloud_devices/common/printer_description_unittest.cc +++ b/components/cloud_devices/common/printer_description_unittest.cc
@@ -194,6 +194,82 @@ " }" "}"; +const char kDocumentTypeColorOnlyCdd[] = + "{" + " 'version': '1.0'," + " 'printer': {" + " 'pwg_raster_config': {" + " 'document_type_supported': [ 'SRGB_8' ]," + " 'document_sheet_back': 'ROTATED'" + " }" + " }" + "}"; + +const char kDocumentTypeGrayOnlyCdd[] = + "{" + " 'version': '1.0'," + " 'printer': {" + " 'pwg_raster_config': {" + " 'document_type_supported': [ 'SGRAY_8' ]," + " 'document_sheet_back': 'ROTATED'" + " }" + " }" + "}"; + +const char kDocumentTypeColorAndGrayCdd[] = + "{" + " 'version': '1.0'," + " 'printer': {" + " 'pwg_raster_config': {" + " 'document_type_supported': [ 'SRGB_8', 'SGRAY_8' ]," + " 'document_sheet_back': 'ROTATED'" + " }" + " }" + "}"; + +const char kDocumentTypeColorAndUnsupportedCdd[] = + "{" + " 'version': '1.0'," + " 'printer': {" + " 'pwg_raster_config': {" + " 'document_type_supported': [ 'SRGB_8', 'SRGB_16' ]," + " 'document_sheet_back': 'ROTATED'" + " }" + " }" + "}"; + +const char kDocumentTypeNoneCdd[] = + "{" + " 'version': '1.0'," + " 'printer': {" + " 'pwg_raster_config': {" + " 'document_sheet_back': 'ROTATED'" + " }" + " }" + "}"; + +const char kDocumentTypeNotStringCdd[] = + "{" + " 'version': '1.0'," + " 'printer': {" + " 'pwg_raster_config': {" + " 'document_type_supported': [ 8, 16 ]," + " 'document_sheet_back': 'ROTATED'" + " }" + " }" + "}"; + +const char kDocumentTypeNotListCdd[] = + "{" + " 'version': '1.0'," + " 'printer': {" + " 'pwg_raster_config': {" + " 'document_type_supported': 'ROTATED'," + " 'document_sheet_back': 'ROTATED'" + " }" + " }" + "}"; + const char kCjt[] = "{" " 'version': '1.0'," @@ -388,6 +464,144 @@ EXPECT_EQ(NormalizeJson(kCdd), NormalizeJson(description.ToString())); } +TEST(PrinterDescriptionTest, CddGetDocumentTypeSupported) { + { + CloudDeviceDescription description; + ASSERT_TRUE( + description.InitFromString(NormalizeJson(kDocumentTypeColorOnlyCdd))); + + PwgRasterConfigCapability pwg_raster; + EXPECT_TRUE(pwg_raster.LoadFrom(description)); + ASSERT_EQ(1U, pwg_raster.value().document_types_supported.size()); + EXPECT_EQ(SRGB_8, pwg_raster.value().document_types_supported[0]); + EXPECT_EQ(ROTATED, pwg_raster.value().document_sheet_back); + EXPECT_FALSE(pwg_raster.value().reverse_order_streaming); + } + { + CloudDeviceDescription description; + ASSERT_TRUE( + description.InitFromString(NormalizeJson(kDocumentTypeGrayOnlyCdd))); + + PwgRasterConfigCapability pwg_raster; + EXPECT_TRUE(pwg_raster.LoadFrom(description)); + ASSERT_EQ(1U, pwg_raster.value().document_types_supported.size()); + EXPECT_EQ(SGRAY_8, pwg_raster.value().document_types_supported[0]); + EXPECT_EQ(ROTATED, pwg_raster.value().document_sheet_back); + EXPECT_FALSE(pwg_raster.value().reverse_order_streaming); + } + { + CloudDeviceDescription description; + ASSERT_TRUE(description.InitFromString( + NormalizeJson(kDocumentTypeColorAndGrayCdd))); + + PwgRasterConfigCapability pwg_raster; + EXPECT_TRUE(pwg_raster.LoadFrom(description)); + ASSERT_EQ(2U, pwg_raster.value().document_types_supported.size()); + EXPECT_EQ(SRGB_8, pwg_raster.value().document_types_supported[0]); + EXPECT_EQ(SGRAY_8, pwg_raster.value().document_types_supported[1]); + EXPECT_EQ(ROTATED, pwg_raster.value().document_sheet_back); + EXPECT_FALSE(pwg_raster.value().reverse_order_streaming); + } + { + CloudDeviceDescription description; + ASSERT_TRUE(description.InitFromString( + NormalizeJson(kDocumentTypeColorAndUnsupportedCdd))); + + PwgRasterConfigCapability pwg_raster; + EXPECT_TRUE(pwg_raster.LoadFrom(description)); + ASSERT_EQ(1U, pwg_raster.value().document_types_supported.size()); + EXPECT_EQ(SRGB_8, pwg_raster.value().document_types_supported[0]); + EXPECT_EQ(ROTATED, pwg_raster.value().document_sheet_back); + EXPECT_FALSE(pwg_raster.value().reverse_order_streaming); + } + { + CloudDeviceDescription description; + ASSERT_TRUE( + description.InitFromString(NormalizeJson(kDocumentTypeNoneCdd))); + + PwgRasterConfigCapability pwg_raster; + EXPECT_TRUE(pwg_raster.LoadFrom(description)); + EXPECT_EQ(0U, pwg_raster.value().document_types_supported.size()); + EXPECT_EQ(ROTATED, pwg_raster.value().document_sheet_back); + EXPECT_FALSE(pwg_raster.value().reverse_order_streaming); + } + { + CloudDeviceDescription description; + ASSERT_TRUE( + description.InitFromString(NormalizeJson(kDocumentTypeNotStringCdd))); + + PwgRasterConfigCapability pwg_raster; + EXPECT_FALSE(pwg_raster.LoadFrom(description)); + } + { + CloudDeviceDescription description; + ASSERT_TRUE( + description.InitFromString(NormalizeJson(kDocumentTypeNotListCdd))); + + PwgRasterConfigCapability pwg_raster; + EXPECT_FALSE(pwg_raster.LoadFrom(description)); + } +} + +TEST(PrinterDescriptionTest, CddSetDocumentTypeSupported) { + { + CloudDeviceDescription description; + + PwgRasterConfig custom_raster; + custom_raster.document_types_supported.push_back(SRGB_8); + custom_raster.document_sheet_back = ROTATED; + + PwgRasterConfigCapability pwg_raster; + pwg_raster.set_value(custom_raster); + pwg_raster.SaveTo(&description); + + EXPECT_EQ(NormalizeJson(kDocumentTypeColorOnlyCdd), + NormalizeJson(description.ToString())); + } + { + CloudDeviceDescription description; + + PwgRasterConfig custom_raster; + custom_raster.document_types_supported.push_back(SGRAY_8); + custom_raster.document_sheet_back = ROTATED; + + PwgRasterConfigCapability pwg_raster; + pwg_raster.set_value(custom_raster); + pwg_raster.SaveTo(&description); + + EXPECT_EQ(NormalizeJson(kDocumentTypeGrayOnlyCdd), + NormalizeJson(description.ToString())); + } + { + CloudDeviceDescription description; + + PwgRasterConfig custom_raster; + custom_raster.document_types_supported.push_back(SRGB_8); + custom_raster.document_types_supported.push_back(SGRAY_8); + custom_raster.document_sheet_back = ROTATED; + + PwgRasterConfigCapability pwg_raster; + pwg_raster.set_value(custom_raster); + pwg_raster.SaveTo(&description); + + EXPECT_EQ(NormalizeJson(kDocumentTypeColorAndGrayCdd), + NormalizeJson(description.ToString())); + } + { + CloudDeviceDescription description; + + PwgRasterConfig custom_raster; + custom_raster.document_sheet_back = ROTATED; + + PwgRasterConfigCapability pwg_raster; + pwg_raster.set_value(custom_raster); + pwg_raster.SaveTo(&description); + + EXPECT_EQ(NormalizeJson(kDocumentTypeNoneCdd), + NormalizeJson(description.ToString())); + } +} + TEST(PrinterDescriptionTest, CddGetAll) { CloudDeviceDescription description; ASSERT_TRUE(description.InitFromString(NormalizeJson(kCdd))); @@ -424,6 +638,7 @@ EXPECT_TRUE(content_types.Contains("image/pwg-raster")); EXPECT_TRUE(content_types.Contains("image/jpeg")); + EXPECT_EQ(0U, pwg_raster_config.value().document_types_supported.size()); EXPECT_EQ(MANUAL_TUMBLE, pwg_raster_config.value().document_sheet_back); EXPECT_TRUE(pwg_raster_config.value().reverse_order_streaming); EXPECT_FALSE(pwg_raster_config.value().rotate_all_pages);
diff --git a/components/exo/buffer.cc b/components/exo/buffer.cc index 3844014..5b350b21 100644 --- a/components/exo/buffer.cc +++ b/components/exo/buffer.cc
@@ -259,9 +259,7 @@ // Create and return a sync token that can be used to ensure that the // BindTexImage2DCHROMIUM call is processed before issuing any commands // that will read from the texture on a different context. - uint64_t fence_sync = gles2->InsertFenceSyncCHROMIUM(); - gles2->OrderingBarrierCHROMIUM(); - gles2->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + gles2->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); TRACE_EVENT_ASYNC_STEP_INTO0("exo", "BufferInUse", gpu_memory_buffer_, "bound"); } @@ -314,9 +312,7 @@ // Create and return a sync token that can be used to ensure that the // CopyTextureCHROMIUM call is processed before issuing any commands // that will read from the target texture on a different context. - uint64_t fence_sync = gles2->InsertFenceSyncCHROMIUM(); - gles2->OrderingBarrierCHROMIUM(); - gles2->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + gles2->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); } return sync_token; }
diff --git a/components/nacl/common/OWNERS b/components/nacl/common/OWNERS index e02997a..cf1061c 100644 --- a/components/nacl/common/OWNERS +++ b/components/nacl/common/OWNERS
@@ -4,5 +4,5 @@ per-file *.mojom=file://ipc/SECURITY_OWNERS per-file *_param_traits*.*=set noparent per-file *_param_traits*.*=file://ipc/SECURITY_OWNERS -per-file *_messages.cc=set noparent -per-file *_messages.cc=file://ipc/SECURITY_OWNERS +per-file *_messages.cc=set noparent +per-file *_messages.cc=file://ipc/SECURITY_OWNERS
diff --git a/components/offline_pages/core/BUILD.gn b/components/offline_pages/core/BUILD.gn index 1721d916..1636825 100644 --- a/components/offline_pages/core/BUILD.gn +++ b/components/offline_pages/core/BUILD.gn
@@ -93,8 +93,8 @@ sources = [ "model/offline_page_item_generator.cc", "model/offline_page_item_generator.h", - "model/offline_page_test_util.cc", - "model/offline_page_test_util.h", + "model/offline_page_test_utils.cc", + "model/offline_page_test_utils.h", "offline_page_metadata_store_test_util.cc", "offline_page_metadata_store_test_util.h", "offline_page_test_archiver.cc",
diff --git a/components/offline_pages/core/model/clear_legacy_temporary_pages_task_unittest.cc b/components/offline_pages/core/model/clear_legacy_temporary_pages_task_unittest.cc index 3031592..57e3497 100644 --- a/components/offline_pages/core/model/clear_legacy_temporary_pages_task_unittest.cc +++ b/components/offline_pages/core/model/clear_legacy_temporary_pages_task_unittest.cc
@@ -13,7 +13,7 @@ #include "components/offline_pages/core/client_namespace_constants.h" #include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/model/offline_page_item_generator.h" -#include "components/offline_pages/core/model/offline_page_test_util.h" +#include "components/offline_pages/core/model/offline_page_test_utils.h" #include "components/offline_pages/core/offline_page_metadata_store_test_util.h" #include "components/offline_pages/core/test_task_runner.h" #include "testing/gtest/include/gtest/gtest.h" @@ -102,14 +102,14 @@ OfflinePageItem page2 = AddPage(kDownloadNamespace, legacy_archives_dir()); EXPECT_EQ(2LL, store_test_util()->GetPageCount()); - EXPECT_EQ(2UL, test_util::GetFileCountInDirectory(legacy_archives_dir())); + EXPECT_EQ(2UL, test_utils::GetFileCountInDirectory(legacy_archives_dir())); auto task = base::MakeUnique<ClearLegacyTemporaryPagesTask>( store(), policy_controller(), legacy_archives_dir()); runner()->RunTask(std::move(task)); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); - EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(legacy_archives_dir())); + EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(legacy_archives_dir())); EXPECT_FALSE(store_test_util()->GetPageByOfflineId(page1.offline_id)); }
diff --git a/components/offline_pages/core/model/clear_storage_task_unittest.cc b/components/offline_pages/core/model/clear_storage_task_unittest.cc index c581cca..4d0a0e3 100644 --- a/components/offline_pages/core/model/clear_storage_task_unittest.cc +++ b/components/offline_pages/core/model/clear_storage_task_unittest.cc
@@ -15,7 +15,7 @@ #include "components/offline_pages/core/client_namespace_constants.h" #include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/model/offline_page_item_generator.h" -#include "components/offline_pages/core/model/offline_page_test_util.h" +#include "components/offline_pages/core/model/offline_page_test_utils.h" #include "components/offline_pages/core/offline_page_metadata_store_test_util.h" #include "components/offline_pages/core/test_task_runner.h" #include "testing/gtest/include/gtest/gtest.h" @@ -210,7 +210,7 @@ EXPECT_EQ(1, total_cleared_times()); EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result()); EXPECT_EQ(2LL, store_test_util()->GetPageCount()); - EXPECT_EQ(2UL, test_util::GetFileCountInDirectory(temp_dir_path())); + EXPECT_EQ(2UL, test_utils::GetFileCountInDirectory(temp_dir_path())); } TEST_F(ClearStorageTaskTest, ClearPagesMoreFreshPages) { @@ -231,7 +231,7 @@ EXPECT_EQ(1, total_cleared_times()); EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result()); EXPECT_EQ(130LL, store_test_util()->GetPageCount()); - EXPECT_EQ(130UL, test_util::GetFileCountInDirectory(temp_dir_path())); + EXPECT_EQ(130UL, test_utils::GetFileCountInDirectory(temp_dir_path())); } TEST_F(ClearStorageTaskTest, TryClearPersistentPages) { @@ -250,7 +250,7 @@ EXPECT_EQ(1, total_cleared_times()); EXPECT_EQ(ClearStorageResult::UNNECESSARY, last_clear_storage_result()); EXPECT_EQ(20LL, store_test_util()->GetPageCount()); - EXPECT_EQ(20UL, test_util::GetFileCountInDirectory(temp_dir_path())); + EXPECT_EQ(20UL, test_utils::GetFileCountInDirectory(temp_dir_path())); } TEST_F(ClearStorageTaskTest, TryClearPersistentPagesWithStoragePressure) { @@ -271,7 +271,7 @@ EXPECT_EQ(1, total_cleared_times()); EXPECT_EQ(ClearStorageResult::UNNECESSARY, last_clear_storage_result()); EXPECT_EQ(20LL, store_test_util()->GetPageCount()); - EXPECT_EQ(20UL, test_util::GetFileCountInDirectory(temp_dir_path())); + EXPECT_EQ(20UL, test_utils::GetFileCountInDirectory(temp_dir_path())); } TEST_F(ClearStorageTaskTest, ClearMultipleTimes) { @@ -311,7 +311,7 @@ EXPECT_EQ(1, total_cleared_times()); EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result()); EXPECT_EQ(90LL, store_test_util()->GetPageCount()); - EXPECT_EQ(90UL, test_util::GetFileCountInDirectory(temp_dir_path())); + EXPECT_EQ(90UL, test_utils::GetFileCountInDirectory(temp_dir_path())); // Advance the clock by the expiration period of bookmark namespace so that // all pages left in that namespace should be expired. @@ -324,7 +324,7 @@ EXPECT_EQ(2, total_cleared_times()); EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result()); EXPECT_EQ(70LL, store_test_util()->GetPageCount()); - EXPECT_EQ(70UL, test_util::GetFileCountInDirectory(temp_dir_path())); + EXPECT_EQ(70UL, test_utils::GetFileCountInDirectory(temp_dir_path())); // Advance the clock by 1 ms, there's no change in pages so the attempt to // clear storage should be unnecessary. @@ -336,7 +336,7 @@ EXPECT_EQ(3, total_cleared_times()); EXPECT_EQ(ClearStorageResult::UNNECESSARY, last_clear_storage_result()); EXPECT_EQ(70LL, store_test_util()->GetPageCount()); - EXPECT_EQ(70UL, test_util::GetFileCountInDirectory(temp_dir_path())); + EXPECT_EQ(70UL, test_utils::GetFileCountInDirectory(temp_dir_path())); // Adding more fresh pages in last_n namespace to make storage usage exceed // limit, so even if only 5 minutes passed from last clearing, this will still @@ -356,7 +356,7 @@ EXPECT_EQ(4, total_cleared_times()); EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result()); EXPECT_EQ(107LL, store_test_util()->GetPageCount()); - EXPECT_EQ(107UL, test_util::GetFileCountInDirectory(temp_dir_path())); + EXPECT_EQ(107UL, test_utils::GetFileCountInDirectory(temp_dir_path())); // Advance the clock by 300 days, in order to expire all temporary pages. Only // 67 temporary pages are left from the last clearing. @@ -368,7 +368,7 @@ EXPECT_EQ(5, total_cleared_times()); EXPECT_EQ(ClearStorageResult::SUCCESS, last_clear_storage_result()); EXPECT_EQ(40LL, store_test_util()->GetPageCount()); - EXPECT_EQ(40UL, test_util::GetFileCountInDirectory(temp_dir_path())); + EXPECT_EQ(40UL, test_utils::GetFileCountInDirectory(temp_dir_path())); } } // namespace offline_pages
diff --git a/components/offline_pages/core/model/delete_page_task.cc b/components/offline_pages/core/model/delete_page_task.cc index 61d8c06..97011a7 100644 --- a/components/offline_pages/core/model/delete_page_task.cc +++ b/components/offline_pages/core/model/delete_page_task.cc
@@ -7,8 +7,11 @@ #include "base/bind.h" #include "base/files/file_path.h" #include "base/files/file_util.h" +#include "base/metrics/histogram_functions.h" +#include "base/time/time.h" #include "build/build_config.h" #include "components/offline_pages/core/client_policy_controller.h" +#include "components/offline_pages/core/model/offline_page_model_utils.h" #include "components/offline_pages/core/offline_page_client_policy.h" #include "components/offline_pages/core/offline_page_metadata_store_sql.h" #include "components/offline_pages/core/offline_page_model.h" @@ -30,6 +33,18 @@ // through the deletion process. This is implementation detail and it will be // used to create OfflinePageModel::DeletedPageInfo that are passed through // callback. +// Please keep WRAPPER_FIELDS, WRAPPER_FIELD_COUNT, the struct declaration of +// DeletedPageInfoWrapper and the method CreateInfoWrapper in sync. +// The WRAPPER_FIELD_COUNT is used for queries which requires more info than the +// fields of INFO_WRAPPER_FIELD, as the additional field can be added manually +// in the SQL query and the result of it can be simply fetched by calling +// statement.Column*(INFO_WRAPPER_COUNT), as it's the last column. For example, +// please take a look at GetCachedDeletedPageInfoWrappersByUrlPredicateSync. +#define INFO_WRAPPER_FIELDS \ + "offline_id, client_namespace, client_id, file_path, request_origin, " \ + "access_count, creation_time" +#define INFO_WRAPPER_FIELD_COUNT 7 + struct DeletedPageInfoWrapper { DeletedPageInfoWrapper(); DeletedPageInfoWrapper(const DeletedPageInfoWrapper& other); @@ -37,12 +52,46 @@ ClientId client_id; base::FilePath file_path; std::string request_origin; + // Used by metric collection only: + int access_count; + base::Time creation_time; }; +DeletedPageInfoWrapper CreateInfoWrapper(const sql::Statement& statement) { + DeletedPageInfoWrapper info_wrapper; + info_wrapper.offline_id = statement.ColumnInt64(0); + info_wrapper.client_id.name_space = statement.ColumnString(1); + info_wrapper.client_id.id = statement.ColumnString(2); + info_wrapper.file_path = + store_utils::FromDatabaseFilePath(statement.ColumnString(3)); + info_wrapper.request_origin = statement.ColumnString(4); + info_wrapper.access_count = statement.ColumnInt(5); + info_wrapper.creation_time = + store_utils::FromDatabaseTime(statement.ColumnInt64(6)); + return info_wrapper; +} + DeletedPageInfoWrapper::DeletedPageInfoWrapper() = default; DeletedPageInfoWrapper::DeletedPageInfoWrapper( const DeletedPageInfoWrapper& other) = default; +void ReportDeletePageHistograms( + const std::vector<DeletedPageInfoWrapper>& info_wrappers) { + const int max_minutes = base::TimeDelta::FromDays(365).InMinutes(); + base::Time delete_time = base::Time::Now(); + for (const auto& info_wrapper : info_wrappers) { + base::UmaHistogramCustomCounts( + model_utils::AddHistogramSuffix(info_wrapper.client_id, + "OfflinePages.PageLifetime"), + (delete_time - info_wrapper.creation_time).InMinutes(), 1, max_minutes, + 100); + base::UmaHistogramCustomCounts( + model_utils::AddHistogramSuffix(info_wrapper.client_id, + "OfflinePages.AccessCount"), + info_wrapper.access_count, 1, 1000000, 50); + } +} + bool DeleteArchiveSync(const base::FilePath& file_path) { // Delete the file only, |false| for recursive. return base::DeleteFile(file_path, false); @@ -74,14 +123,17 @@ if (info_wrappers.size() == 0) return DeletePageTaskResult(DeletePageResult::SUCCESS, deleted_page_infos); + ReportDeletePageHistograms(info_wrappers); + bool any_archive_deleted = false; for (const auto& info_wrapper : info_wrappers) { if (DeleteArchiveSync(info_wrapper.file_path)) { any_archive_deleted = true; - if (DeletePageEntryByOfflineIdSync(db, info_wrapper.offline_id)) + if (DeletePageEntryByOfflineIdSync(db, info_wrapper.offline_id)) { deleted_page_infos.emplace_back(info_wrapper.offline_id, info_wrapper.client_id, info_wrapper.request_origin); + } } } // If there're no files deleted, return DEVICE_FAILURE. @@ -99,18 +151,13 @@ int64_t offline_id, DeletedPageInfoWrapper* info_wrapper) { static const char kSql[] = - "SELECT client_namespace, client_id, file_path, request_origin" - " FROM " OFFLINE_PAGES_TABLE_NAME " WHERE offline_id = ?"; + "SELECT " INFO_WRAPPER_FIELDS " FROM " OFFLINE_PAGES_TABLE_NAME + " WHERE offline_id = ?"; sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); statement.BindInt64(0, offline_id); if (statement.Step()) { - info_wrapper->offline_id = offline_id; - info_wrapper->client_id.name_space = statement.ColumnString(0); - info_wrapper->client_id.id = statement.ColumnString(1); - info_wrapper->file_path = - store_utils::FromDatabaseFilePath(statement.ColumnString(2)); - info_wrapper->request_origin = statement.ColumnString(3); + *info_wrapper = CreateInfoWrapper(statement); return true; } return false; @@ -151,22 +198,15 @@ ClientId client_id) { std::vector<DeletedPageInfoWrapper> info_wrappers; static const char kSql[] = - "SELECT offline_id, file_path, request_origin" - " FROM " OFFLINE_PAGES_TABLE_NAME + "SELECT " INFO_WRAPPER_FIELDS " FROM " OFFLINE_PAGES_TABLE_NAME " WHERE client_namespace = ? AND client_id = ?"; sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); statement.BindString(0, client_id.name_space); statement.BindString(1, client_id.id); - while (statement.Step()) { - DeletedPageInfoWrapper info_wrapper; - info_wrapper.client_id = client_id; - info_wrapper.offline_id = statement.ColumnInt64(0); - info_wrapper.file_path = - store_utils::FromDatabaseFilePath(statement.ColumnString(1)); - info_wrapper.request_origin = statement.ColumnString(2); - info_wrappers.push_back(info_wrapper); - } + while (statement.Step()) + info_wrappers.emplace_back(CreateInfoWrapper(statement)); + return info_wrappers; } @@ -209,8 +249,8 @@ const UrlPredicate& url_predicate) { std::vector<DeletedPageInfoWrapper> info_wrappers; static const char kSql[] = - "SELECT offline_id, client_namespace, client_id, file_path," - " request_origin, online_url" + "SELECT " INFO_WRAPPER_FIELDS + ", online_url" " FROM " OFFLINE_PAGES_TABLE_NAME " WHERE client_namespace = ?"; for (const auto& temp_namespace : temp_namespaces) { @@ -218,15 +258,10 @@ statement.BindString(0, temp_namespace); while (statement.Step()) { - if (!url_predicate.Run(GURL(statement.ColumnString(5)))) + if (!url_predicate.Run( + GURL(statement.ColumnString(INFO_WRAPPER_FIELD_COUNT)))) continue; - DeletedPageInfoWrapper info_wrapper; - info_wrapper.offline_id = statement.ColumnInt64(0); - info_wrapper.client_id.name_space = statement.ColumnString(1); - info_wrapper.client_id.id = statement.ColumnString(2); - info_wrapper.file_path = - store_utils::FromDatabaseFilePath(statement.ColumnString(3)); - info_wrapper.request_origin = statement.ColumnString(4); + DeletedPageInfoWrapper info_wrapper = CreateInfoWrapper(statement); info_wrappers.push_back(info_wrapper); } } @@ -269,9 +304,7 @@ size_t limit) { std::vector<DeletedPageInfoWrapper> info_wrappers; static const char kSql[] = - "SELECT offline_id, client_namespace, client_id, file_path," - " request_origin" - " FROM " OFFLINE_PAGES_TABLE_NAME + "SELECT " INFO_WRAPPER_FIELDS " FROM " OFFLINE_PAGES_TABLE_NAME " WHERE client_namespace = ? AND online_url = ?" " ORDER BY last_access_time ASC"; sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql)); @@ -279,13 +312,7 @@ statement.BindString(1, url.spec()); while (statement.Step()) { - DeletedPageInfoWrapper info_wrapper; - info_wrapper.offline_id = statement.ColumnInt64(0); - info_wrapper.client_id.name_space = statement.ColumnString(1); - info_wrapper.client_id.id = statement.ColumnString(2); - info_wrapper.file_path = - store_utils::FromDatabaseFilePath(statement.ColumnString(3)); - info_wrapper.request_origin = statement.ColumnString(4); + DeletedPageInfoWrapper info_wrapper = CreateInfoWrapper(statement); info_wrappers.push_back(info_wrapper); }
diff --git a/components/offline_pages/core/model/delete_page_task_unittest.cc b/components/offline_pages/core/model/delete_page_task_unittest.cc index 7c6369d..8df7352d 100644 --- a/components/offline_pages/core/model/delete_page_task_unittest.cc +++ b/components/offline_pages/core/model/delete_page_task_unittest.cc
@@ -13,11 +13,13 @@ #include "base/files/scoped_temp_dir.h" #include "base/memory/weak_ptr.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/histogram_tester.h" #include "base/test/test_mock_time_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "components/offline_pages/core/client_namespace_constants.h" #include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/model/offline_page_item_generator.h" +#include "components/offline_pages/core/model/offline_page_model_utils.h" #include "components/offline_pages/core/offline_page_item.h" #include "components/offline_pages/core/offline_page_metadata_store_test_util.h" #include "components/offline_pages/core/offline_page_model.h" @@ -67,6 +69,7 @@ } OfflinePageItemGenerator* generator() { return &generator_; } TestTaskRunner* runner() { return &runner_; } + base::HistogramTester* histogram_tester() { return histogram_tester_.get(); } DeletePageResult last_delete_page_result() { return last_delete_page_result_; } @@ -82,6 +85,7 @@ std::unique_ptr<ClientPolicyController> policy_controller_; OfflinePageItemGenerator generator_; TestTaskRunner runner_; + std::unique_ptr<base::HistogramTester> histogram_tester_; base::ScopedTempDir temp_dir_; DeletePageResult last_delete_page_result_; @@ -102,6 +106,7 @@ store_test_util_.BuildStoreInMemory(); policy_controller_ = base::MakeUnique<ClientPolicyController>(); generator()->SetArchiveDirectory(temp_dir()); + histogram_tester_ = base::MakeUnique<base::HistogramTester>(); } void DeletePageTaskTest::TearDown() { @@ -139,6 +144,8 @@ generator()->SetNamespace(kTestNamespace); OfflinePageItem page1 = generator()->CreateItemWithTempFile(); OfflinePageItem page2 = generator()->CreateItemWithTempFile(); + // Set an access count of 200 to avoid falling in the same bucket. + generator()->SetAccessCount(200); OfflinePageItem page3 = generator()->CreateItemWithTempFile(); store_test_util()->InsertItem(page1); @@ -162,6 +169,22 @@ EXPECT_TRUE(CheckPageDeleted(page1)); EXPECT_FALSE(CheckPageDeleted(page2)); EXPECT_TRUE(CheckPageDeleted(page3)); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.PageLifetime"), + 2); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.AccessCount"), + 2); + histogram_tester()->ExpectBucketCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.AccessCount"), + 0, 1); + histogram_tester()->ExpectBucketCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.AccessCount"), + 200, 1); } TEST_F(DeletePageTaskTest, DeletePageByOfflineIdNotFound) { @@ -191,6 +214,14 @@ EXPECT_FALSE(CheckPageDeleted(page1)); EXPECT_FALSE(CheckPageDeleted(page2)); EXPECT_FALSE(CheckPageDeleted(page3)); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.PageLifetime"), + 0); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.AccessCount"), + 0); } TEST_F(DeletePageTaskTest, DeletePageByClientId) { @@ -198,6 +229,7 @@ generator()->SetNamespace(kTestNamespace); OfflinePageItem page1 = generator()->CreateItemWithTempFile(); OfflinePageItem page2 = generator()->CreateItemWithTempFile(); + generator()->SetAccessCount(200); OfflinePageItem page3 = generator()->CreateItemWithTempFile(); store_test_util()->InsertItem(page1); store_test_util()->InsertItem(page2); @@ -219,6 +251,22 @@ EXPECT_TRUE(CheckPageDeleted(page1)); EXPECT_FALSE(CheckPageDeleted(page2)); EXPECT_TRUE(CheckPageDeleted(page3)); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.PageLifetime"), + 2); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.AccessCount"), + 2); + histogram_tester()->ExpectBucketCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.AccessCount"), + 0, 1); + histogram_tester()->ExpectBucketCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.AccessCount"), + 200, 1); } TEST_F(DeletePageTaskTest, DeletePageByClientIdNotFound) { @@ -244,6 +292,14 @@ EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_page_result()); EXPECT_EQ(0UL, last_deleted_page_infos().size()); EXPECT_EQ(3LL, store_test_util()->GetPageCount()); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.PageLifetime"), + 0); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.AccessCount"), + 0); } TEST_F(DeletePageTaskTest, DeletePageByUrlPredicate) { @@ -251,6 +307,7 @@ generator()->SetNamespace(kTestNamespace); generator()->SetUrl(kTestUrl1); OfflinePageItem page1 = generator()->CreateItemWithTempFile(); + generator()->SetAccessCount(200); OfflinePageItem page2 = generator()->CreateItemWithTempFile(); generator()->SetUrl(kTestUrl2); OfflinePageItem page3 = generator()->CreateItemWithTempFile(); @@ -278,6 +335,22 @@ EXPECT_EQ(predicate.Run(page1.url), CheckPageDeleted(page1)); EXPECT_EQ(predicate.Run(page2.url), CheckPageDeleted(page2)); EXPECT_EQ(predicate.Run(page3.url), CheckPageDeleted(page3)); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.PageLifetime"), + 2); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.AccessCount"), + 2); + histogram_tester()->ExpectBucketCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.AccessCount"), + 0, 1); + histogram_tester()->ExpectBucketCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.AccessCount"), + 200, 1); } TEST_F(DeletePageTaskTest, DeletePageByUrlPredicateNotFound) { @@ -311,6 +384,14 @@ EXPECT_FALSE(CheckPageDeleted(page1)); EXPECT_FALSE(CheckPageDeleted(page2)); EXPECT_FALSE(CheckPageDeleted(page3)); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.PageLifetime"), + 0); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.AccessCount"), + 0); } TEST_F(DeletePageTaskTest, DeletePageForPageLimit) { @@ -345,6 +426,14 @@ EXPECT_TRUE(CheckPageDeleted(page1)); EXPECT_FALSE(CheckPageDeleted(page2)); EXPECT_FALSE(CheckPageDeleted(page3)); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.PageLifetime"), + 1); + histogram_tester()->ExpectUniqueSample( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.AccessCount"), + 0, 1); } TEST_F(DeletePageTaskTest, DeletePageForPageLimit_UnlimitedNamespace) { @@ -374,6 +463,14 @@ // should be success with no page deleted. EXPECT_EQ(DeletePageResult::SUCCESS, last_delete_page_result()); EXPECT_EQ(0UL, last_deleted_page_infos().size()); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.PageLifetime"), + 0); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.AccessCount"), + 0); } // This test is disabled since it's lacking the ability of mocking store failure
diff --git a/components/offline_pages/core/model/offline_page_item_generator.cc b/components/offline_pages/core/model/offline_page_item_generator.cc index 0c2615568..94a04dc 100644 --- a/components/offline_pages/core/model/offline_page_item_generator.cc +++ b/components/offline_pages/core/model/offline_page_item_generator.cc
@@ -29,6 +29,7 @@ item.original_url = original_url_; item.file_size = file_size_; item.last_access_time = last_access_time_; + item.access_count = access_count_; return item; } @@ -71,11 +72,14 @@ file_size_ = file_size; } -void OfflinePageItemGenerator::SetLastAccessTime( - const base::Time& last_access_time) { +void OfflinePageItemGenerator::SetLastAccessTime(base::Time last_access_time) { last_access_time_ = last_access_time; } +void OfflinePageItemGenerator::SetAccessCount(int access_count) { + access_count_ = access_count; +} + void OfflinePageItemGenerator::SetArchiveDirectory( const base::FilePath& archive_dir) { archive_dir_ = archive_dir;
diff --git a/components/offline_pages/core/model/offline_page_item_generator.h b/components/offline_pages/core/model/offline_page_item_generator.h index f40fe520..70274c79 100644 --- a/components/offline_pages/core/model/offline_page_item_generator.h +++ b/components/offline_pages/core/model/offline_page_item_generator.h
@@ -30,8 +30,9 @@ void SetRequestOrigin(const std::string& request_origin); void SetUrl(const GURL& url); void SetOriginalUrl(const GURL& url); - void SetFileSize(int64_t); - void SetLastAccessTime(const base::Time& time); + void SetFileSize(int64_t file_size); + void SetLastAccessTime(base::Time time); + void SetAccessCount(int access_count); void SetArchiveDirectory(const base::FilePath& archive_dir); private: @@ -42,6 +43,7 @@ GURL original_url_; int64_t file_size_ = 0; base::Time last_access_time_; + int access_count_ = 0; base::FilePath archive_dir_; }; } // namespace offline_pages
diff --git a/components/offline_pages/core/model/offline_page_model_taskified.cc b/components/offline_pages/core/model/offline_page_model_taskified.cc index cc14fd1..a901469 100644 --- a/components/offline_pages/core/model/offline_page_model_taskified.cc +++ b/components/offline_pages/core/model/offline_page_model_taskified.cc
@@ -93,6 +93,22 @@ return SavePageResult::STORE_FAILURE; } +void ReportPageHistogramAfterSuccessfulSaving( + const OfflinePageItem& offline_page, + const base::Time& save_time) { + base::UmaHistogramCustomTimes( + model_utils::AddHistogramSuffix(offline_page.client_id, + "OfflinePages.SavePageTime"), + save_time - offline_page.creation_time, + base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromSeconds(10), + 50); + + base::UmaHistogramCustomCounts( + model_utils::AddHistogramSuffix(offline_page.client_id, + "OfflinePages.PageSize"), + offline_page.file_size / 1024, 1, 10000, 50); +} + } // namespace OfflinePageModelTaskified::OfflinePageModelTaskified( @@ -292,6 +308,11 @@ "OfflinePages.SavePageCount", model_utils::ToNamespaceEnum(page.client_id.name_space), OfflinePagesNamespaceEnumeration::RESULT_COUNT); + base::UmaHistogramEnumeration( + model_utils::AddHistogramSuffix(page.client_id, + "OfflinePages.SavePageResult"), + result, SavePageResult::RESULT_COUNT); + if (result == SavePageResult::ARCHIVE_CREATION_FAILED) CreateArchivesDirectoryIfNeeded(); if (!callback.is_null()) @@ -342,8 +363,10 @@ SavePageResult save_page_result = AddPageResultToSavePageResult(add_page_result); InformSavePageDone(callback, save_page_result, page_attempted); - if (save_page_result == SavePageResult::SUCCESS) + if (save_page_result == SavePageResult::SUCCESS) { + ReportPageHistogramAfterSuccessfulSaving(page_attempted, GetCurrentTime()); RemovePagesMatchingUrlAndNamespace(page_attempted); + } PostClearCachedPagesTask(false /* is_initializing */); } @@ -357,19 +380,14 @@ } } -// TODO(romax): see if this method can be moved into anonymous namespace after -// migrating UMAs. -void OfflinePageModelTaskified::InformDeletePageDone( - const DeletePageCallback& callback, - DeletePageResult result) { - if (!callback.is_null()) - callback.Run(result); -} - void OfflinePageModelTaskified::OnDeleteDone( const DeletePageCallback& callback, DeletePageResult result, const std::vector<OfflinePageModel::DeletedPageInfo>& infos) { + UMA_HISTOGRAM_ENUMERATION("OfflinePages.DeletePageResult", result, + DeletePageResult::RESULT_COUNT); + + // Notify observers and run callback. for (const auto& info : infos) { UMA_HISTOGRAM_ENUMERATION( "OfflinePages.DeletePageCount", @@ -378,7 +396,8 @@ for (Observer& observer : observers_) observer.OfflinePageDeleted(info); } - InformDeletePageDone(callback, result); + if (!callback.is_null()) + callback.Run(result); } void OfflinePageModelTaskified::PostClearLegacyTemporaryPagesTask() {
diff --git a/components/offline_pages/core/model/offline_page_model_taskified.h b/components/offline_pages/core/model/offline_page_model_taskified.h index 8c0f1877..d41e9a1 100644 --- a/components/offline_pages/core/model/offline_page_model_taskified.h +++ b/components/offline_pages/core/model/offline_page_model_taskified.h
@@ -144,8 +144,6 @@ AddPageResult result); // Callbacks for deleting pages. - void InformDeletePageDone(const DeletePageCallback& callback, - DeletePageResult result); void OnDeleteDone( const DeletePageCallback& callback, DeletePageResult result,
diff --git a/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc b/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc index 5f0efbc..df4f31a 100644 --- a/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc +++ b/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc
@@ -19,7 +19,7 @@ #include "components/offline_pages/core/client_namespace_constants.h" #include "components/offline_pages/core/model/offline_page_item_generator.h" #include "components/offline_pages/core/model/offline_page_model_utils.h" -#include "components/offline_pages/core/model/offline_page_test_util.h" +#include "components/offline_pages/core/model/offline_page_test_utils.h" #include "components/offline_pages/core/offline_page_item.h" #include "components/offline_pages/core/offline_page_metadata_store_sql.h" #include "components/offline_pages/core/offline_page_metadata_store_test_util.h" @@ -180,6 +180,7 @@ BuildModel(); PumpLoop(); CheckTaskQueueIdle(); + histogram_tester_ = base::MakeUnique<base::HistogramTester>(); } void OfflinePageModelTaskifiedTest::TearDown() { @@ -304,7 +305,7 @@ kTestUrl, kTestClientId1, kTestUrl2, kEmptyRequestOrigin, std::move(archiver), SavePageResult::SUCCESS); - EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(temporary_dir_path())); + EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(temporary_dir_path())); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); auto saved_page_ptr = store_test_util()->GetPageByOfflineId(offline_id); ASSERT_TRUE(saved_page_ptr); @@ -326,6 +327,17 @@ static_cast<int>( model_utils::ToNamespaceEnum(saved_page_ptr->client_id.name_space)), 1); + histogram_tester()->ExpectUniqueSample( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.SavePageResult"), + static_cast<int>(SavePageResult::SUCCESS), 1); + histogram_tester()->ExpectUniqueSample( + model_utils::AddHistogramSuffix(kTestClientId1, "OfflinePages.PageSize"), + kTestFileSize / 1024, 1); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.SavePageTime"), + 1); } TEST_F(OfflinePageModelTaskifiedTest, SavePageSuccessfulWithSameOriginalUrl) { @@ -336,7 +348,7 @@ kTestUrl, kTestClientId1, kTestUrl, kEmptyRequestOrigin, std::move(archiver), SavePageResult::SUCCESS); - EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(temporary_dir_path())); + EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(temporary_dir_path())); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); auto saved_page_ptr = store_test_util()->GetPageByOfflineId(offline_id); ASSERT_TRUE(saved_page_ptr); @@ -350,6 +362,17 @@ static_cast<int>( model_utils::ToNamespaceEnum(saved_page_ptr->client_id.name_space)), 1); + histogram_tester()->ExpectUniqueSample( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.SavePageResult"), + static_cast<int>(SavePageResult::SUCCESS), 1); + histogram_tester()->ExpectUniqueSample( + model_utils::AddHistogramSuffix(kTestClientId1, "OfflinePages.PageSize"), + kTestFileSize / 1024, 1); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.SavePageTime"), + 1); } TEST_F(OfflinePageModelTaskifiedTest, SavePageSuccessfulWithRequestOrigin) { @@ -358,7 +381,7 @@ kTestUrl, kTestClientId1, kTestUrl2, kTestRequestOrigin, std::move(archiver), SavePageResult::SUCCESS); - EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(temporary_dir_path())); + EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(temporary_dir_path())); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); auto saved_page_ptr = store_test_util()->GetPageByOfflineId(offline_id); ASSERT_TRUE(saved_page_ptr); @@ -379,6 +402,17 @@ static_cast<int>( model_utils::ToNamespaceEnum(saved_page_ptr->client_id.name_space)), 1); + histogram_tester()->ExpectUniqueSample( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.SavePageResult"), + static_cast<int>(SavePageResult::SUCCESS), 1); + histogram_tester()->ExpectUniqueSample( + model_utils::AddHistogramSuffix(kTestClientId1, "OfflinePages.PageSize"), + kTestFileSize / 1024, 1); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.SavePageTime"), + 1); } TEST_F(OfflinePageModelTaskifiedTest, SavePageOfflineArchiverCancelled) { @@ -391,6 +425,17 @@ "OfflinePages.SavePageCount", static_cast<int>(model_utils::ToNamespaceEnum(kTestClientId1.name_space)), 1); + histogram_tester()->ExpectUniqueSample( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.SavePageResult"), + static_cast<int>(SavePageResult::CANCELLED), 1); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(kTestClientId1, "OfflinePages.PageSize"), + 0); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.SavePageTime"), + 0); } TEST_F(OfflinePageModelTaskifiedTest, SavePageOfflineArchiverDeviceFull) { @@ -403,6 +448,17 @@ "OfflinePages.SavePageCount", static_cast<int>(model_utils::ToNamespaceEnum(kTestClientId1.name_space)), 1); + histogram_tester()->ExpectUniqueSample( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.SavePageResult"), + static_cast<int>(SavePageResult::DEVICE_FULL), 1); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(kTestClientId1, "OfflinePages.PageSize"), + 0); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.SavePageTime"), + 0); } TEST_F(OfflinePageModelTaskifiedTest, @@ -417,6 +473,17 @@ "OfflinePages.SavePageCount", static_cast<int>(model_utils::ToNamespaceEnum(kTestClientId1.name_space)), 1); + histogram_tester()->ExpectUniqueSample( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.SavePageResult"), + static_cast<int>(SavePageResult::CONTENT_UNAVAILABLE), 1); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(kTestClientId1, "OfflinePages.PageSize"), + 0); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.SavePageTime"), + 0); } TEST_F(OfflinePageModelTaskifiedTest, SavePageOfflineCreationFailed) { @@ -430,6 +497,17 @@ "OfflinePages.SavePageCount", static_cast<int>(model_utils::ToNamespaceEnum(kTestClientId1.name_space)), 1); + histogram_tester()->ExpectUniqueSample( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.SavePageResult"), + static_cast<int>(SavePageResult::ARCHIVE_CREATION_FAILED), 1); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(kTestClientId1, "OfflinePages.PageSize"), + 0); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.SavePageTime"), + 0); } TEST_F(OfflinePageModelTaskifiedTest, SavePageOfflineArchiverReturnedWrongUrl) { @@ -443,6 +521,17 @@ "OfflinePages.SavePageCount", static_cast<int>(model_utils::ToNamespaceEnum(kTestClientId1.name_space)), 1); + histogram_tester()->ExpectUniqueSample( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.SavePageResult"), + static_cast<int>(SavePageResult::ARCHIVE_CREATION_FAILED), 1); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(kTestClientId1, "OfflinePages.PageSize"), + 0); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.SavePageTime"), + 0); } // This test is disabled since it's lacking the ability of mocking store failure @@ -460,6 +549,17 @@ "OfflinePages.SavePageCount", static_cast<int>(model_utils::ToNamespaceEnum(kTestClientId1.name_space)), 1); + histogram_tester()->ExpectUniqueSample( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.SavePageResult"), + static_cast<int>(SavePageResult::SKIPPED), 1); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(kTestClientId1, "OfflinePages.PageSize"), + 0); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.SavePageTime"), + 0); } TEST_F(OfflinePageModelTaskifiedTest, SavePageOfflineArchiverTwoPages) { @@ -491,7 +591,7 @@ SavePageWithCallback(kTestUrl2, kTestClientId2, GURL(), kTestRequestOrigin, std::move(archiver), callback.Get()); - EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(temporary_dir_path())); + EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(temporary_dir_path())); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); base::FilePath saved_file_path1 = last_path_created_by_archiver(); @@ -507,7 +607,7 @@ PumpLoop(); // Check that offline_id1 refers to the second save page request. - EXPECT_EQ(2UL, test_util::GetFileCountInDirectory(temporary_dir_path())); + EXPECT_EQ(2UL, test_utils::GetFileCountInDirectory(temporary_dir_path())); EXPECT_EQ(2LL, store_test_util()->GetPageCount()); base::FilePath saved_file_path2 = last_path_created_by_archiver(); @@ -531,6 +631,17 @@ "OfflinePages.SavePageCount", static_cast<int>(model_utils::ToNamespaceEnum(kTestClientId1.name_space)), 2); + histogram_tester()->ExpectUniqueSample( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.SavePageResult"), + static_cast<int>(SavePageResult::SUCCESS), 2); + histogram_tester()->ExpectUniqueSample( + model_utils::AddHistogramSuffix(kTestClientId1, "OfflinePages.PageSize"), + kTestFileSize / 1024, 2); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.SavePageTime"), + 2); } TEST_F(OfflinePageModelTaskifiedTest, AddPage) { @@ -606,11 +717,12 @@ TEST_F(OfflinePageModelTaskifiedTest, DeletePagesByOfflineId) { page_generator()->SetArchiveDirectory(temporary_dir_path()); + page_generator()->SetNamespace(kDefaultNamespace); OfflinePageItem page1 = page_generator()->CreateItemWithTempFile(); OfflinePageItem page2 = page_generator()->CreateItemWithTempFile(); InsertPageIntoStore(page1); InsertPageIntoStore(page2); - EXPECT_EQ(2UL, test_util::GetFileCountInDirectory(temporary_dir_path())); + EXPECT_EQ(2UL, test_utils::GetFileCountInDirectory(temporary_dir_path())); EXPECT_EQ(2LL, store_test_util()->GetPageCount()); base::MockCallback<DeletePageCallback> callback; @@ -623,13 +735,24 @@ PumpLoop(); EXPECT_TRUE(observer_delete_page_called()); EXPECT_EQ(last_deleted_page_info().offline_id, page1.offline_id); - EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(temporary_dir_path())); + EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(temporary_dir_path())); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); histogram_tester()->ExpectUniqueSample( "OfflinePages.DeletePageCount", static_cast<int>( model_utils::ToNamespaceEnum(page1.client_id.name_space)), 1); + histogram_tester()->ExpectUniqueSample( + "OfflinePages.DeletePageResult", + static_cast<int>(DeletePageResult::SUCCESS), 1); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.PageLifetime"), + 1); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.AccessCount"), + 1); } TEST_F(OfflinePageModelTaskifiedTest, DeletePagesByUrlPredicate) { @@ -641,7 +764,7 @@ OfflinePageItem page2 = page_generator()->CreateItemWithTempFile(); InsertPageIntoStore(page1); InsertPageIntoStore(page2); - EXPECT_EQ(2UL, test_util::GetFileCountInDirectory(temporary_dir_path())); + EXPECT_EQ(2UL, test_utils::GetFileCountInDirectory(temporary_dir_path())); EXPECT_EQ(2LL, store_test_util()->GetPageCount()); base::MockCallback<DeletePageCallback> callback; @@ -659,13 +782,24 @@ PumpLoop(); EXPECT_TRUE(observer_delete_page_called()); EXPECT_EQ(last_deleted_page_info().offline_id, page1.offline_id); - EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(temporary_dir_path())); + EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(temporary_dir_path())); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); histogram_tester()->ExpectUniqueSample( "OfflinePages.DeletePageCount", static_cast<int>( model_utils::ToNamespaceEnum(page1.client_id.name_space)), 1); + histogram_tester()->ExpectUniqueSample( + "OfflinePages.DeletePageResult", + static_cast<int>(DeletePageResult::SUCCESS), 1); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.PageLifetime"), + 1); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(page1.client_id, + "OfflinePages.AccessCount"), + 1); } TEST_F(OfflinePageModelTaskifiedTest, GetPageByOfflineId) { @@ -838,7 +972,7 @@ OfflinePageItem page2 = page_generator()->CreateItemWithTempFile(); InsertPageIntoStore(page1); InsertPageIntoStore(page2); - EXPECT_EQ(2UL, test_util::GetFileCountInDirectory(temporary_dir_path())); + EXPECT_EQ(2UL, test_utils::GetFileCountInDirectory(temporary_dir_path())); EXPECT_EQ(2LL, store_test_util()->GetPageCount()); base::MockCallback<DeletePageCallback> callback; @@ -851,13 +985,24 @@ PumpLoop(); EXPECT_TRUE(observer_delete_page_called()); EXPECT_EQ(last_deleted_page_info().client_id, page1.client_id); - EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(temporary_dir_path())); + EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(temporary_dir_path())); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); histogram_tester()->ExpectUniqueSample( "OfflinePages.DeletePageCount", static_cast<int>( model_utils::ToNamespaceEnum(page1.client_id.name_space)), 1); + histogram_tester()->ExpectUniqueSample( + "OfflinePages.DeletePageResult", + static_cast<int>(DeletePageResult::SUCCESS), 1); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.PageLifetime"), + 1); + histogram_tester()->ExpectTotalCount( + model_utils::AddHistogramSuffix(kTestClientId1, + "OfflinePages.AccessCount"), + 1); } TEST_F(OfflinePageModelTaskifiedTest, GetPagesByNamespace) { @@ -1076,16 +1221,16 @@ PumpLoop(); EXPECT_EQ(4LL, store_test_util()->GetPageCount()); - EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(temporary_dir_path())); - EXPECT_EQ(3UL, test_util::GetFileCountInDirectory(persistent_dir_path())); + EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(temporary_dir_path())); + EXPECT_EQ(3UL, test_utils::GetFileCountInDirectory(persistent_dir_path())); // Rebuild the model in order to trigger consistency check. BuildModel(); task_runner()->FastForwardBy(base::TimeDelta::FromSeconds(20)); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); - EXPECT_EQ(0UL, test_util::GetFileCountInDirectory(temporary_dir_path())); - EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(persistent_dir_path())); + EXPECT_EQ(0UL, test_utils::GetFileCountInDirectory(temporary_dir_path())); + EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(persistent_dir_path())); } TEST_F(OfflinePageModelTaskifiedTest, ClearStorage) {
diff --git a/components/offline_pages/core/model/offline_page_model_utils.cc b/components/offline_pages/core/model/offline_page_model_utils.cc index 06b91b312..b517a63 100644 --- a/components/offline_pages/core/model/offline_page_model_utils.cc +++ b/components/offline_pages/core/model/offline_page_model_utils.cc
@@ -8,6 +8,7 @@ #include "base/logging.h" #include "components/offline_pages/core/client_namespace_constants.h" +#include "components/offline_pages/core/offline_page_item.h" namespace offline_pages { @@ -38,6 +39,18 @@ return OfflinePagesNamespaceEnumeration::DEFAULT; } +std::string AddHistogramSuffix(const ClientId& client_id, + const char* histogram_name) { + if (client_id.name_space.empty()) { + NOTREACHED(); + return histogram_name; + } + std::string adjusted_histogram_name(histogram_name); + adjusted_histogram_name += "."; + adjusted_histogram_name += client_id.name_space; + return adjusted_histogram_name; +} + } // namespace model_utils } // namespace offline_pages
diff --git a/components/offline_pages/core/model/offline_page_model_utils.h b/components/offline_pages/core/model/offline_page_model_utils.h index c161717a..671e34f7 100644 --- a/components/offline_pages/core/model/offline_page_model_utils.h +++ b/components/offline_pages/core/model/offline_page_model_utils.h
@@ -10,11 +10,17 @@ namespace offline_pages { enum class OfflinePagesNamespaceEnumeration; +struct ClientId; namespace model_utils { +// Return the enum value of the namespace represented by |name_space|. OfflinePagesNamespaceEnumeration ToNamespaceEnum(const std::string& name_space); +// Metric collection related. +std::string AddHistogramSuffix(const ClientId& client_id, + const char* histogram_name); + } // namespace model_utils } // namespace offline_pages
diff --git a/components/offline_pages/core/model/offline_page_test_util.cc b/components/offline_pages/core/model/offline_page_test_utils.cc similarity index 83% rename from components/offline_pages/core/model/offline_page_test_util.cc rename to components/offline_pages/core/model/offline_page_test_utils.cc index 5867ac1..763e594 100644 --- a/components/offline_pages/core/model/offline_page_test_util.cc +++ b/components/offline_pages/core/model/offline_page_test_utils.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 "components/offline_pages/core/offline_store_utils.h" +#include "components/offline_pages/core/model/offline_page_test_utils.h" #include "base/files/file_enumerator.h" namespace offline_pages { -namespace test_util { +namespace test_utils { size_t GetFileCountInDirectory(const base::FilePath& directory) { base::FileEnumerator file_enumerator(directory, false, @@ -21,6 +21,6 @@ return count; } -} // namespace test_util +} // namespace test_utils } // namespace offline_pages
diff --git a/components/offline_pages/core/model/offline_page_test_util.h b/components/offline_pages/core/model/offline_page_test_utils.h similarity index 84% rename from components/offline_pages/core/model/offline_page_test_util.h rename to components/offline_pages/core/model/offline_page_test_utils.h index 958e7bb..421d1b45e 100644 --- a/components/offline_pages/core/model/offline_page_test_util.h +++ b/components/offline_pages/core/model/offline_page_test_utils.h
@@ -17,14 +17,14 @@ namespace offline_pages { -// The test_util namespace within offline_pages namespace contains helper +// The test_utils namespace within offline_pages namespace contains helper // methods that are common and shared among all Offline Pages tests. -namespace test_util { +namespace test_utils { // Get number of files in the given |dir|. size_t GetFileCountInDirectory(const base::FilePath& directory); -} // namespace test_util +} // namespace test_utils } // namespace offline_pages
diff --git a/components/offline_pages/core/model/persistent_pages_consistency_check_task_unittest.cc b/components/offline_pages/core/model/persistent_pages_consistency_check_task_unittest.cc index 023b4498..261d41e4 100644 --- a/components/offline_pages/core/model/persistent_pages_consistency_check_task_unittest.cc +++ b/components/offline_pages/core/model/persistent_pages_consistency_check_task_unittest.cc
@@ -14,7 +14,7 @@ #include "components/offline_pages/core/client_namespace_constants.h" #include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/model/offline_page_item_generator.h" -#include "components/offline_pages/core/model/offline_page_test_util.h" +#include "components/offline_pages/core/model/offline_page_test_utils.h" #include "components/offline_pages/core/offline_page_metadata_store_test_util.h" #include "components/offline_pages/core/test_task_runner.h" #include "testing/gtest/include/gtest/gtest.h" @@ -136,14 +136,14 @@ OfflinePageItem page2 = AddPage(kDownloadNamespace, persistent_dir()); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); - EXPECT_EQ(2UL, test_util::GetFileCountInDirectory(persistent_dir())); + EXPECT_EQ(2UL, test_utils::GetFileCountInDirectory(persistent_dir())); auto task = base::MakeUnique<PersistentPagesConsistencyCheckTask>( store(), policy_controller(), persistent_dir()); runner()->RunTask(std::move(task)); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); - EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(persistent_dir())); + EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(persistent_dir())); EXPECT_FALSE(IsPageRemovedFromBothPlaces(page1)); EXPECT_TRUE(IsPageRemovedFromBothPlaces(page2)); histogram_tester()->ExpectTotalCount( @@ -176,14 +176,14 @@ OfflinePageItem page2 = AddPage(kDownloadNamespace, persistent_dir()); EXPECT_EQ(2LL, store_test_util()->GetPageCount()); - EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(persistent_dir())); + EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(persistent_dir())); auto task = base::MakeUnique<PersistentPagesConsistencyCheckTask>( store(), policy_controller(), persistent_dir()); runner()->RunTask(std::move(task)); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); - EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(persistent_dir())); + EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(persistent_dir())); EXPECT_FALSE(IsPageRemovedFromBothPlaces(page1)); EXPECT_TRUE(IsPageRemovedFromBothPlaces(page2)); histogram_tester()->ExpectTotalCount( @@ -217,14 +217,14 @@ OfflinePageItem page3 = AddPage(kDownloadNamespace, persistent_dir()); EXPECT_EQ(2LL, store_test_util()->GetPageCount()); - EXPECT_EQ(2UL, test_util::GetFileCountInDirectory(persistent_dir())); + EXPECT_EQ(2UL, test_utils::GetFileCountInDirectory(persistent_dir())); auto task = base::MakeUnique<PersistentPagesConsistencyCheckTask>( store(), policy_controller(), persistent_dir()); runner()->RunTask(std::move(task)); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); - EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(persistent_dir())); + EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(persistent_dir())); EXPECT_FALSE(IsPageRemovedFromBothPlaces(page1)); EXPECT_TRUE(IsPageRemovedFromBothPlaces(page2)); EXPECT_TRUE(IsPageRemovedFromBothPlaces(page3)); @@ -251,14 +251,14 @@ EXPECT_TRUE(base::Move(path, mp3_path)); EXPECT_EQ(0LL, store_test_util()->GetPageCount()); - EXPECT_EQ(2UL, test_util::GetFileCountInDirectory(persistent_dir())); + EXPECT_EQ(2UL, test_utils::GetFileCountInDirectory(persistent_dir())); auto task = base::MakeUnique<PersistentPagesConsistencyCheckTask>( store(), policy_controller(), persistent_dir()); runner()->RunTask(std::move(task)); EXPECT_EQ(0LL, store_test_util()->GetPageCount()); - EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(persistent_dir())); + EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(persistent_dir())); EXPECT_TRUE(IsPageRemovedFromBothPlaces(page1)); histogram_tester()->ExpectTotalCount( "OfflinePages.ConsistencyCheck.Persistent.PagesMissingArchiveFileCount",
diff --git a/components/offline_pages/core/model/temporary_pages_consistency_check_task_unittest.cc b/components/offline_pages/core/model/temporary_pages_consistency_check_task_unittest.cc index fc1b9ab72..8c87f8c 100644 --- a/components/offline_pages/core/model/temporary_pages_consistency_check_task_unittest.cc +++ b/components/offline_pages/core/model/temporary_pages_consistency_check_task_unittest.cc
@@ -14,7 +14,7 @@ #include "components/offline_pages/core/client_namespace_constants.h" #include "components/offline_pages/core/client_policy_controller.h" #include "components/offline_pages/core/model/offline_page_item_generator.h" -#include "components/offline_pages/core/model/offline_page_test_util.h" +#include "components/offline_pages/core/model/offline_page_test_utils.h" #include "components/offline_pages/core/offline_page_metadata_store_test_util.h" #include "components/offline_pages/core/test_task_runner.h" #include "testing/gtest/include/gtest/gtest.h" @@ -134,14 +134,14 @@ OfflinePageItem page2 = AddPage(kLastNNamespace, temporary_dir()); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); - EXPECT_EQ(2UL, test_util::GetFileCountInDirectory(temporary_dir())); + EXPECT_EQ(2UL, test_utils::GetFileCountInDirectory(temporary_dir())); auto task = base::MakeUnique<TemporaryPagesConsistencyCheckTask>( store(), policy_controller(), temporary_dir()); runner()->RunTask(std::move(task)); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); - EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(temporary_dir())); + EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(temporary_dir())); EXPECT_FALSE(IsPageRemovedFromBothPlaces(page1)); EXPECT_TRUE(IsPageRemovedFromBothPlaces(page2)); histogram_tester()->ExpectTotalCount( @@ -173,14 +173,14 @@ OfflinePageItem page2 = AddPage(kLastNNamespace, temporary_dir()); EXPECT_EQ(2LL, store_test_util()->GetPageCount()); - EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(temporary_dir())); + EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(temporary_dir())); auto task = base::MakeUnique<TemporaryPagesConsistencyCheckTask>( store(), policy_controller(), temporary_dir()); runner()->RunTask(std::move(task)); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); - EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(temporary_dir())); + EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(temporary_dir())); EXPECT_FALSE(IsPageRemovedFromBothPlaces(page1)); EXPECT_TRUE(IsPageRemovedFromBothPlaces(page2)); histogram_tester()->ExpectTotalCount( @@ -214,14 +214,14 @@ OfflinePageItem page3 = AddPage(kLastNNamespace, temporary_dir()); EXPECT_EQ(2LL, store_test_util()->GetPageCount()); - EXPECT_EQ(2UL, test_util::GetFileCountInDirectory(temporary_dir())); + EXPECT_EQ(2UL, test_utils::GetFileCountInDirectory(temporary_dir())); auto task = base::MakeUnique<TemporaryPagesConsistencyCheckTask>( store(), policy_controller(), temporary_dir()); runner()->RunTask(std::move(task)); EXPECT_EQ(1LL, store_test_util()->GetPageCount()); - EXPECT_EQ(1UL, test_util::GetFileCountInDirectory(temporary_dir())); + EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(temporary_dir())); EXPECT_FALSE(IsPageRemovedFromBothPlaces(page1)); EXPECT_TRUE(IsPageRemovedFromBothPlaces(page2)); EXPECT_TRUE(IsPageRemovedFromBothPlaces(page3));
diff --git a/components/offline_pages/core/offline_page_item.cc b/components/offline_pages/core/offline_page_item.cc index bd08b83..5790e3c 100644 --- a/components/offline_pages/core/offline_page_item.cc +++ b/components/offline_pages/core/offline_page_item.cc
@@ -81,7 +81,7 @@ request_origin == other.request_origin && system_download_id == other.system_download_id && file_missing_time == other.file_missing_time && - upgrade_attempt == other.upgrade_attempt && digest == digest; + upgrade_attempt == other.upgrade_attempt && digest == other.digest; } bool OfflinePageItem::operator<(const OfflinePageItem& other) const {
diff --git a/components/printing/common/print_messages.h b/components/printing/common/print_messages.h index 8affd68..6d02771 100644 --- a/components/printing/common/print_messages.h +++ b/components/printing/common/print_messages.h
@@ -330,14 +330,6 @@ // node, depending on which mode the RenderFrame is in. IPC_MESSAGE_ROUTED0(PrintMsg_PrintNodeUnderContextMenu) -#if BUILDFLAG(ENABLE_BASIC_PRINTING) && BUILDFLAG(ENABLE_PRINT_PREVIEW) -// Tells the renderer to print the print preview tab's PDF plugin without -// showing the print dialog. (This is the final step in the print preview -// workflow.) -IPC_MESSAGE_ROUTED1(PrintMsg_PrintForPrintPreview, - base::DictionaryValue /* settings */) -#endif // BUILDFLAG(ENABLE_BASIC_PRINTING) && BUILDFLAG(ENABLE_PRINT_PREVIEW) - #if BUILDFLAG(ENABLE_BASIC_PRINTING) // Tells the RenderFrame to switch the CSS to print media type, renders every // requested pages and switch back the CSS to display media type.
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc index 5a94031..fc5c545 100644 --- a/components/printing/renderer/print_render_frame_helper.cc +++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -946,7 +946,6 @@ ignore_css_margins_(false), is_printing_enabled_(true), notify_browser_of_print_failure_(true), - print_for_preview_(false), delegate_(std::move(delegate)), print_node_in_progress_(false), is_loading_(false), @@ -1045,9 +1044,6 @@ IPC_MESSAGE_HANDLER(PrintMsg_PrintPages, OnPrintPages) IPC_MESSAGE_HANDLER(PrintMsg_PrintForSystemDialog, OnPrintForSystemDialog) #endif // BUILDFLAG(ENABLE_BASIC_PRINTING) -#if BUILDFLAG(ENABLE_BASIC_PRINTING) && BUILDFLAG(ENABLE_PRINT_PREVIEW) - IPC_MESSAGE_HANDLER(PrintMsg_PrintForPrintPreview, OnPrintForPrintPreview) -#endif #if BUILDFLAG(ENABLE_PRINT_PREVIEW) IPC_MESSAGE_HANDLER(PrintMsg_InitiatePrintPreview, OnInitiatePrintPreview) IPC_MESSAGE_HANDLER(PrintMsg_PrintPreview, OnPrintPreview) @@ -1111,68 +1107,6 @@ } #endif // BUILDFLAG(ENABLE_BASIC_PRINTING) -#if BUILDFLAG(ENABLE_BASIC_PRINTING) && BUILDFLAG(ENABLE_PRINT_PREVIEW) -void PrintRenderFrameHelper::OnPrintForPrintPreview( - const base::DictionaryValue& job_settings) { - CHECK_LE(ipc_nesting_level_, 1); - // If still not finished with earlier print request simply ignore. - if (prep_frame_view_) - return; - - blink::WebDocument document = render_frame()->GetWebFrame()->GetDocument(); - // <object>/<iframe> with id="pdf-viewer" is created in - // chrome/browser/resources/print_preview/print_preview.js - blink::WebElement pdf_element = document.GetElementById("pdf-viewer"); - if (pdf_element.IsNull()) { - NOTREACHED(); - return; - } - - // The out-of-process plugin element is nested within a frame. In tests, there - // may not be an iframe containing the out-of-process plugin, so continue with - // the element with ID "pdf-viewer" if it isn't an iframe. - blink::WebLocalFrame* plugin_frame = pdf_element.GetDocument().GetFrame(); - blink::WebElement plugin_element = pdf_element; - if (pdf_element.HasHTMLTagName("iframe")) { - plugin_frame = blink::WebLocalFrame::FromFrameOwnerElement(pdf_element); - plugin_element = delegate_->GetPdfElement(plugin_frame); - if (plugin_element.IsNull()) { - NOTREACHED(); - return; - } - } - - // Set |print_for_preview_| flag and autoreset it to back to original - // on return. - base::AutoReset<bool> set_printing_flag(&print_for_preview_, true); - - if (!UpdatePrintSettings(plugin_frame, plugin_element, job_settings)) { - LOG(ERROR) << "UpdatePrintSettings failed"; - DidFinishPrinting(FAIL_PRINT); - return; - } - - // Print page onto entire page not just printable area. Preview PDF already - // has content in correct position taking into account page size and printable - // area. - // TODO(vitalybuka) : Make this consistent on all platform. This change - // affects Windows only. Linux and OSX RenderPagesForPrint do not use - // printable_area. Also we can't change printable_area deeper inside - // RenderPagesForPrint for Windows, because it's used also by native - // printing and it expects real printable_area value. - // See http://crbug.com/123408 - PrintMsg_Print_Params& print_params = print_pages_params_->params; - printer_printable_area_ = print_params.printable_area; - print_params.printable_area = gfx::Rect(print_params.page_size); - - // Render Pages for printing. - if (!RenderPagesForPrint(plugin_frame, plugin_element)) { - LOG(ERROR) << "RenderPagesForPrint failed"; - DidFinishPrinting(FAIL_PRINT); - } -} -#endif // BUILDFLAG(ENABLE_BASIC_PRINTING) && BUILDFLAG(ENABLE_PRINT_PREVIEW) - void PrintRenderFrameHelper::GetPageSizeAndContentAreaFromPageLayout( const PageSizeMargins& page_layout_in_points, gfx::Size* page_size, @@ -1828,21 +1762,13 @@ const base::DictionaryValue* job_settings = &passed_job_settings; base::DictionaryValue modified_job_settings; if (job_settings->empty()) { - if (!print_for_preview_) - print_preview_context_.set_error(PREVIEW_ERROR_BAD_SETTING); + print_preview_context_.set_error(PREVIEW_ERROR_BAD_SETTING); return false; } - bool source_is_html = true; - if (print_for_preview_) { - if (!job_settings->GetBoolean(kSettingPreviewModifiable, &source_is_html)) { - NOTREACHED(); - } - } else { - source_is_html = !PrintingNodeOrPdfFrame(frame, node); - } + bool source_is_html = !PrintingNodeOrPdfFrame(frame, node); - if (print_for_preview_ || !source_is_html) { + if (!source_is_html) { modified_job_settings.MergeDictionary(job_settings); modified_job_settings.SetBoolean(kSettingHeaderFooterEnabled, false); modified_job_settings.SetInteger(kSettingMarginsType, NO_MARGINS); @@ -1868,32 +1794,27 @@ return false; } - if (!print_for_preview_) { - // Validate expected print preview settings. - if (!job_settings->GetInteger(kPreviewRequestID, - &settings.params.preview_request_id) || - !job_settings->GetBoolean(kIsFirstRequest, - &settings.params.is_first_request)) { - NOTREACHED(); - print_preview_context_.set_error(PREVIEW_ERROR_BAD_SETTING); - return false; - } - - settings.params.print_to_pdf = IsPrintToPdfRequested(*job_settings); - UpdateFrameMarginsCssInfo(*job_settings); - settings.params.print_scaling_option = GetPrintScalingOption( - frame, node, source_is_html, *job_settings, settings.params); + // Validate expected print preview settings. + if (!job_settings->GetInteger(kPreviewRequestID, + &settings.params.preview_request_id) || + !job_settings->GetBoolean(kIsFirstRequest, + &settings.params.is_first_request)) { + NOTREACHED(); + print_preview_context_.set_error(PREVIEW_ERROR_BAD_SETTING); + return false; } + settings.params.print_to_pdf = IsPrintToPdfRequested(*job_settings); + UpdateFrameMarginsCssInfo(*job_settings); + settings.params.print_scaling_option = GetPrintScalingOption( + frame, node, source_is_html, *job_settings, settings.params); + SetPrintPagesParams(settings); if (PrintMsg_Print_Params_IsValid(settings.params)) return true; - if (print_for_preview_) - Send(new PrintHostMsg_ShowInvalidPrinterSettingsError(routing_id())); - else - print_preview_context_.set_error(PREVIEW_ERROR_INVALID_PRINTER_SETTINGS); + print_preview_context_.set_error(PREVIEW_ERROR_INVALID_PRINTER_SETTINGS); return false; } #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW)
diff --git a/components/printing/renderer/print_render_frame_helper.h b/components/printing/renderer/print_render_frame_helper.h index cd174ca6..b96f5b17 100644 --- a/components/printing/renderer/print_render_frame_helper.h +++ b/components/printing/renderer/print_render_frame_helper.h
@@ -185,7 +185,6 @@ #if BUILDFLAG(ENABLE_BASIC_PRINTING) void OnPrintPages(); void OnPrintForSystemDialog(); - void OnPrintForPrintPreview(const base::DictionaryValue& job_settings); #endif // BUILDFLAG(ENABLE_BASIC_PRINTING) #if BUILDFLAG(ENABLE_PRINT_PREVIEW) void OnInitiatePrintPreview(bool has_selection); @@ -384,9 +383,6 @@ // the failure came from the browser in the first place. bool notify_browser_of_print_failure_; - // True, when printing from print preview. - bool print_for_preview_; - // Used to check the prerendering status. const std::unique_ptr<Delegate> delegate_;
diff --git a/components/printing/test/print_render_frame_helper_browsertest.cc b/components/printing/test/print_render_frame_helper_browsertest.cc index 1fb7b38..4a4c055c 100644 --- a/components/printing/test/print_render_frame_helper_browsertest.cc +++ b/components/printing/test/print_render_frame_helper_browsertest.cc
@@ -214,20 +214,6 @@ } #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) -#if defined(OS_WIN) - // Verifies that the correct page size was returned. - void VerifyPrintedPageSize(const gfx::Size& expected_page_size) { - const IPC::Message* print_msg = - render_thread_->sink().GetUniqueMessageMatching( - PrintHostMsg_DidPrintDocument::ID); - PrintHostMsg_DidPrintDocument::Param post_did_print_page_param; - PrintHostMsg_DidPrintDocument::Read(print_msg, &post_did_print_page_param); - gfx::Size page_size_received = - std::get<0>(post_did_print_page_param).page_size; - EXPECT_EQ(expected_page_size, page_size_received); - } -#endif - // Verifies whether the pages printed or not. void VerifyPagesPrinted(bool expect_printed) { const IPC::Message* print_msg = @@ -279,13 +265,6 @@ } #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) -#if BUILDFLAG(ENABLE_BASIC_PRINTING) - void OnPrintForPrintPreview(const base::DictionaryValue& dict) { - GetPrintRenderFrameHelper()->OnPrintForPrintPreview(dict); - base::RunLoop().RunUntilIdle(); - } -#endif // BUILDFLAG(ENABLE_BASIC_PRINTING) - PrintRenderFrameHelper* GetPrintRenderFrameHelper() { return PrintRenderFrameHelper::Get( content::RenderFrame::FromWebFrame(GetMainFrame())); @@ -1217,70 +1196,6 @@ VerifyPagesPrinted(false); } -#if BUILDFLAG(ENABLE_BASIC_PRINTING) -// Tests that printing from print preview works and sending and receiving -// messages through that channel all works. -TEST_F(MAYBE_PrintRenderFrameHelperPreviewTest, OnPrintForPrintPreview) { - LoadHTML(kPrintPreviewHTML); - - // Fill in some dummy values. - base::DictionaryValue dict; - CreatePrintSettingsDictionary(&dict); - OnPrintForPrintPreview(dict); - - VerifyPrintFailed(false); - VerifyPagesPrinted(true); -} - -// Tests that when printing non-default scaling values, the page size returned -// by PrintRenderFrameHelper is still the real physical page size. See -// crbug.com/686384 -TEST_F(MAYBE_PrintRenderFrameHelperPreviewTest, - OnPrintForPrintPreviewWithScaling) { - LoadHTML(kPrintPreviewHTML); - - // Fill in some dummy values. - base::DictionaryValue dict; - CreatePrintSettingsDictionary(&dict); - - // Media size - gfx::Size page_size_in = gfx::Size(240, 480); - float device_microns_per_unit = - (printing::kHundrethsMMPerInch * 10.0f) / printing::kDefaultPdfDpi; - int height_microns = - static_cast<int>(page_size_in.height() * device_microns_per_unit); - int width_microns = - static_cast<int>(page_size_in.width() * device_microns_per_unit); - auto media_size = base::MakeUnique<base::DictionaryValue>(); - media_size->SetInteger(kSettingMediaSizeHeightMicrons, height_microns); - media_size->SetInteger(kSettingMediaSizeWidthMicrons, width_microns); - - // Non default scaling value - dict.SetInteger(kSettingScaleFactor, 80); - dict.Set(kSettingMediaSize, std::move(media_size)); - - OnPrintForPrintPreview(dict); - - VerifyPrintFailed(false); - VerifyPagesPrinted(true); -#if defined(OS_WIN) - VerifyPrintedPageSize(page_size_in); -#endif -} - -// Tests that printing from print preview fails and receiving error messages -// through that channel all works. -TEST_F(MAYBE_PrintRenderFrameHelperPreviewTest, OnPrintForPrintPreviewFail) { - LoadHTML(kPrintPreviewHTML); - - // An empty dictionary should fail. - base::DictionaryValue empty_dict; - OnPrintForPrintPreview(empty_dict); - - VerifyPagesPrinted(false); -} -#endif // BUILDFLAG(ENABLE_BASIC_PRINTING) - // Tests that when default printer has invalid printer settings, print preview // receives error message. TEST_F(MAYBE_PrintRenderFrameHelperPreviewTest, @@ -1344,23 +1259,6 @@ VerifyPrintPreviewGenerated(false); } -#if BUILDFLAG(ENABLE_BASIC_PRINTING) -TEST_F(MAYBE_PrintRenderFrameHelperPreviewTest, - OnPrintForPrintPreviewUsingInvalidPrinterSettings) { - LoadHTML(kPrintPreviewHTML); - - // Set mock printer to provide invalid settings. - print_render_thread_->printer()->UseInvalidSettings(); - - // Fill in some dummy values. - base::DictionaryValue dict; - CreatePrintSettingsDictionary(&dict); - OnPrintForPrintPreview(dict); - - VerifyPrintFailed(true); - VerifyPagesPrinted(false); -} -#endif // BUILDFLAG(ENABLE_BASIC_PRINTING) #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) #endif // !defined(OS_CHROMEOS)
diff --git a/components/sessions/content/content_serialized_navigation_builder.cc b/components/sessions/content/content_serialized_navigation_builder.cc index 7ca46a0..57944fc 100644 --- a/components/sessions/content/content_serialized_navigation_builder.cc +++ b/components/sessions/content/content_serialized_navigation_builder.cc
@@ -13,10 +13,27 @@ #include "content/public/browser/favicon_status.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_entry.h" +#include "content/public/browser/replaced_navigation_entry_data.h" #include "content/public/common/page_state.h" #include "content/public/common/referrer.h" namespace sessions { +namespace { + +base::Optional<SerializedNavigationEntry::ReplacedNavigationEntryData> +ConvertReplacedEntryData( + const base::Optional<content::ReplacedNavigationEntryData>& input_data) { + if (!input_data.has_value()) + return base::nullopt; + + SerializedNavigationEntry::ReplacedNavigationEntryData output_data; + output_data.first_committed_url = input_data->first_committed_url; + output_data.first_timestamp = input_data->first_timestamp; + output_data.first_transition_type = input_data->first_transition_type; + return output_data; +} + +} // namespace // static SerializedNavigationEntry @@ -44,6 +61,8 @@ navigation.favicon_url_ = entry.GetFavicon().url; navigation.http_status_code_ = entry.GetHttpStatusCode(); navigation.redirect_chain_ = entry.GetRedirectChain(); + navigation.replaced_entry_data_ = + ConvertReplacedEntryData(entry.GetReplacedEntryData()); navigation.password_state_ = GetPasswordStateFromNavigation(entry); for (const auto& handler_entry :
diff --git a/components/sessions/core/serialized_navigation_entry.cc b/components/sessions/core/serialized_navigation_entry.cc index f8d12d7..b89cff1 100644 --- a/components/sessions/core/serialized_navigation_entry.cc +++ b/components/sessions/core/serialized_navigation_entry.cc
@@ -19,6 +19,110 @@ // The previous referrer policy value corresponding to |Never|. const int kObsoleteReferrerPolicyNever = 2; +namespace { + +sync_pb::SyncEnums_PageTransition ToSyncPageTransition( + ui::PageTransition transition_type) { + switch (ui::PageTransitionStripQualifier(transition_type)) { + case ui::PAGE_TRANSITION_LINK: + return sync_pb::SyncEnums_PageTransition_LINK; + + case ui::PAGE_TRANSITION_TYPED: + return sync_pb::SyncEnums_PageTransition_TYPED; + + case ui::PAGE_TRANSITION_AUTO_BOOKMARK: + return sync_pb::SyncEnums_PageTransition_AUTO_BOOKMARK; + + case ui::PAGE_TRANSITION_AUTO_SUBFRAME: + return sync_pb::SyncEnums_PageTransition_AUTO_SUBFRAME; + + case ui::PAGE_TRANSITION_MANUAL_SUBFRAME: + return sync_pb::SyncEnums_PageTransition_MANUAL_SUBFRAME; + + case ui::PAGE_TRANSITION_GENERATED: + return sync_pb::SyncEnums_PageTransition_GENERATED; + + case ui::PAGE_TRANSITION_AUTO_TOPLEVEL: + return sync_pb::SyncEnums_PageTransition_AUTO_TOPLEVEL; + + case ui::PAGE_TRANSITION_FORM_SUBMIT: + return sync_pb::SyncEnums_PageTransition_FORM_SUBMIT; + + case ui::PAGE_TRANSITION_RELOAD: + return sync_pb::SyncEnums_PageTransition_RELOAD; + + case ui::PAGE_TRANSITION_KEYWORD: + return sync_pb::SyncEnums_PageTransition_KEYWORD; + + case ui::PAGE_TRANSITION_KEYWORD_GENERATED: + return sync_pb::SyncEnums_PageTransition_KEYWORD_GENERATED; + + // Non-core values listed here although unreachable: + case ui::PAGE_TRANSITION_CORE_MASK: + case ui::PAGE_TRANSITION_BLOCKED: + case ui::PAGE_TRANSITION_FORWARD_BACK: + case ui::PAGE_TRANSITION_FROM_ADDRESS_BAR: + case ui::PAGE_TRANSITION_HOME_PAGE: + case ui::PAGE_TRANSITION_FROM_API: + case ui::PAGE_TRANSITION_CHAIN_START: + case ui::PAGE_TRANSITION_CHAIN_END: + case ui::PAGE_TRANSITION_CLIENT_REDIRECT: + case ui::PAGE_TRANSITION_SERVER_REDIRECT: + case ui::PAGE_TRANSITION_IS_REDIRECT_MASK: + case ui::PAGE_TRANSITION_QUALIFIER_MASK: + break; + } + NOTREACHED(); + return sync_pb::SyncEnums_PageTransition_LINK; +} + +ui::PageTransition FromSyncPageTransition( + sync_pb::SyncEnums_PageTransition transition_type) { + switch (transition_type) { + case sync_pb::SyncEnums_PageTransition_LINK: + return ui::PAGE_TRANSITION_LINK; + + case sync_pb::SyncEnums_PageTransition_TYPED: + return ui::PAGE_TRANSITION_TYPED; + + case sync_pb::SyncEnums_PageTransition_AUTO_BOOKMARK: + return ui::PAGE_TRANSITION_AUTO_BOOKMARK; + + case sync_pb::SyncEnums_PageTransition_AUTO_SUBFRAME: + return ui::PAGE_TRANSITION_AUTO_SUBFRAME; + + case sync_pb::SyncEnums_PageTransition_MANUAL_SUBFRAME: + return ui::PAGE_TRANSITION_MANUAL_SUBFRAME; + + case sync_pb::SyncEnums_PageTransition_GENERATED: + return ui::PAGE_TRANSITION_GENERATED; + + case sync_pb::SyncEnums_PageTransition_AUTO_TOPLEVEL: + return ui::PAGE_TRANSITION_AUTO_TOPLEVEL; + + case sync_pb::SyncEnums_PageTransition_FORM_SUBMIT: + return ui::PAGE_TRANSITION_FORM_SUBMIT; + + case sync_pb::SyncEnums_PageTransition_RELOAD: + return ui::PAGE_TRANSITION_RELOAD; + + case sync_pb::SyncEnums_PageTransition_KEYWORD: + return ui::PAGE_TRANSITION_KEYWORD; + + case sync_pb::SyncEnums_PageTransition_KEYWORD_GENERATED: + return ui::PAGE_TRANSITION_KEYWORD_GENERATED; + } + return ui::PAGE_TRANSITION_LINK; +} + +} // namespace + +size_t +SerializedNavigationEntry::ReplacedNavigationEntryData::EstimateMemoryUsage() + const { + return base::trace_event::EstimateMemoryUsage(first_committed_url); +} + SerializedNavigationEntry::SerializedNavigationEntry() { referrer_policy_ = SerializedNavigationDriver::Get()->GetDefaultReferrerPolicy(); @@ -59,47 +163,7 @@ navigation.virtual_url_ = GURL(sync_data.virtual_url()); navigation.title_ = base::UTF8ToUTF16(sync_data.title()); - uint32_t transition = 0; - if (sync_data.has_page_transition()) { - switch (sync_data.page_transition()) { - case sync_pb::SyncEnums_PageTransition_LINK: - transition = ui::PAGE_TRANSITION_LINK; - break; - case sync_pb::SyncEnums_PageTransition_TYPED: - transition = ui::PAGE_TRANSITION_TYPED; - break; - case sync_pb::SyncEnums_PageTransition_AUTO_BOOKMARK: - transition = ui::PAGE_TRANSITION_AUTO_BOOKMARK; - break; - case sync_pb::SyncEnums_PageTransition_AUTO_SUBFRAME: - transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME; - break; - case sync_pb::SyncEnums_PageTransition_MANUAL_SUBFRAME: - transition = ui::PAGE_TRANSITION_MANUAL_SUBFRAME; - break; - case sync_pb::SyncEnums_PageTransition_GENERATED: - transition = ui::PAGE_TRANSITION_GENERATED; - break; - case sync_pb::SyncEnums_PageTransition_AUTO_TOPLEVEL: - transition = ui::PAGE_TRANSITION_AUTO_TOPLEVEL; - break; - case sync_pb::SyncEnums_PageTransition_FORM_SUBMIT: - transition = ui::PAGE_TRANSITION_FORM_SUBMIT; - break; - case sync_pb::SyncEnums_PageTransition_RELOAD: - transition = ui::PAGE_TRANSITION_RELOAD; - break; - case sync_pb::SyncEnums_PageTransition_KEYWORD: - transition = ui::PAGE_TRANSITION_KEYWORD; - break; - case sync_pb::SyncEnums_PageTransition_KEYWORD_GENERATED: - transition = ui::PAGE_TRANSITION_KEYWORD_GENERATED; - break; - default: - transition = ui::PAGE_TRANSITION_LINK; - break; - } - } + uint32_t transition = FromSyncPageTransition(sync_data.page_transition()); if (sync_data.has_redirect_type()) { switch (sync_data.redirect_type()) { @@ -136,6 +200,17 @@ navigation.http_status_code_ = sync_data.http_status_code(); + if (sync_data.has_replaced_navigation()) { + navigation.replaced_entry_data_ = ReplacedNavigationEntryData(); + navigation.replaced_entry_data_->first_committed_url = + GURL(sync_data.replaced_navigation().first_committed_url()); + navigation.replaced_entry_data_->first_timestamp = syncer::ProtoTimeToTime( + sync_data.replaced_navigation().first_timestamp_msec()); + navigation.replaced_entry_data_->first_transition_type = + FromSyncPageTransition( + sync_data.replaced_navigation().first_page_transition()); + } + SerializedNavigationDriver::Get()->Sanitize(&navigation); navigation.is_restored_ = true; @@ -364,54 +439,7 @@ static_cast<int32_t>(ui::PAGE_TRANSITION_KEYWORD_GENERATED), "PAGE_TRANSITION_LAST_CORE must equal " "PAGE_TRANSITION_KEYWORD_GENERATED"); - switch (ui::PageTransitionStripQualifier(transition_type_)) { - case ui::PAGE_TRANSITION_LINK: - sync_data.set_page_transition( - sync_pb::SyncEnums_PageTransition_LINK); - break; - case ui::PAGE_TRANSITION_TYPED: - sync_data.set_page_transition( - sync_pb::SyncEnums_PageTransition_TYPED); - break; - case ui::PAGE_TRANSITION_AUTO_BOOKMARK: - sync_data.set_page_transition( - sync_pb::SyncEnums_PageTransition_AUTO_BOOKMARK); - break; - case ui::PAGE_TRANSITION_AUTO_SUBFRAME: - sync_data.set_page_transition( - sync_pb::SyncEnums_PageTransition_AUTO_SUBFRAME); - break; - case ui::PAGE_TRANSITION_MANUAL_SUBFRAME: - sync_data.set_page_transition( - sync_pb::SyncEnums_PageTransition_MANUAL_SUBFRAME); - break; - case ui::PAGE_TRANSITION_GENERATED: - sync_data.set_page_transition( - sync_pb::SyncEnums_PageTransition_GENERATED); - break; - case ui::PAGE_TRANSITION_AUTO_TOPLEVEL: - sync_data.set_page_transition( - sync_pb::SyncEnums_PageTransition_AUTO_TOPLEVEL); - break; - case ui::PAGE_TRANSITION_FORM_SUBMIT: - sync_data.set_page_transition( - sync_pb::SyncEnums_PageTransition_FORM_SUBMIT); - break; - case ui::PAGE_TRANSITION_RELOAD: - sync_data.set_page_transition( - sync_pb::SyncEnums_PageTransition_RELOAD); - break; - case ui::PAGE_TRANSITION_KEYWORD: - sync_data.set_page_transition( - sync_pb::SyncEnums_PageTransition_KEYWORD); - break; - case ui::PAGE_TRANSITION_KEYWORD_GENERATED: - sync_data.set_page_transition( - sync_pb::SyncEnums_PageTransition_KEYWORD_GENERATED); - break; - default: - NOTREACHED(); - } + sync_data.set_page_transition(ToSyncPageTransition(transition_type_)); // Page transition qualifiers. if (ui::PageTransitionIsRedirect(transition_type_)) { @@ -474,6 +502,17 @@ } } + if (replaced_entry_data_.has_value()) { + sync_pb::ReplacedNavigation* replaced_navigation = + sync_data.mutable_replaced_navigation(); + replaced_navigation->set_first_committed_url( + replaced_entry_data_->first_committed_url.spec()); + replaced_navigation->set_first_timestamp_msec( + syncer::TimeToProtoTime(replaced_entry_data_->first_timestamp)); + replaced_navigation->set_first_page_transition( + ToSyncPageTransition(replaced_entry_data_->first_transition_type)); + } + sync_data.set_is_restored(is_restored_); return sync_data; @@ -481,16 +520,16 @@ size_t SerializedNavigationEntry::EstimateMemoryUsage() const { using base::trace_event::EstimateMemoryUsage; - return - EstimateMemoryUsage(referrer_url_) + - EstimateMemoryUsage(virtual_url_) + - EstimateMemoryUsage(title_) + - EstimateMemoryUsage(encoded_page_state_) + - EstimateMemoryUsage(original_request_url_) + - EstimateMemoryUsage(favicon_url_) + - EstimateMemoryUsage(redirect_chain_) + - EstimateMemoryUsage(content_pack_categories_) + - EstimateMemoryUsage(extended_info_map_); + return EstimateMemoryUsage(referrer_url_) + + EstimateMemoryUsage(virtual_url_) + EstimateMemoryUsage(title_) + + EstimateMemoryUsage(encoded_page_state_) + + EstimateMemoryUsage(original_request_url_) + + EstimateMemoryUsage(favicon_url_) + + EstimateMemoryUsage(redirect_chain_) + + EstimateMemoryUsage( + replaced_entry_data_.value_or(ReplacedNavigationEntryData())) + + EstimateMemoryUsage(content_pack_categories_) + + EstimateMemoryUsage(extended_info_map_); } } // namespace sessions
diff --git a/components/sessions/core/serialized_navigation_entry.h b/components/sessions/core/serialized_navigation_entry.h index 1b39150..cb17bfc 100644 --- a/components/sessions/core/serialized_navigation_entry.h +++ b/components/sessions/core/serialized_navigation_entry.h
@@ -13,6 +13,7 @@ #include <string> #include <vector> +#include "base/optional.h" #include "base/strings/string16.h" #include "base/time/time.h" #include "components/sessions/core/sessions_export.h" @@ -142,6 +143,23 @@ } const std::vector<GURL>& redirect_chain() const { return redirect_chain_; } + // This class is analogous to content::ReplacedNavigationEntryData. + // When a history entry is replaced (e.g. history.replaceState()), this + // contains some information about the entry prior to being replaced. Even if + // an entry is replaced multiple times, it represents data prior to the + // *first* replace. + struct ReplacedNavigationEntryData { + size_t EstimateMemoryUsage() const; + + GURL first_committed_url; + base::Time first_timestamp; + ui::PageTransition first_transition_type; + }; + const base::Optional<ReplacedNavigationEntryData>& replaced_entry_data() + const { + return replaced_entry_data_; + } + const std::map<std::string, std::string>& extended_info_map() const { return extended_info_map_; } @@ -176,6 +194,8 @@ int http_status_code_ = 0; bool is_restored_ = false; // Not persisted. std::vector<GURL> redirect_chain_; // Not persisted. + base::Optional<ReplacedNavigationEntryData> + replaced_entry_data_; // Not persisted. // Additional information. BlockedState blocked_state_ = STATE_INVALID;
diff --git a/components/sessions/core/serialized_navigation_entry_test_helper.cc b/components/sessions/core/serialized_navigation_entry_test_helper.cc index 5913d2e..516974c1 100644 --- a/components/sessions/core/serialized_navigation_entry_test_helper.cc +++ b/components/sessions/core/serialized_navigation_entry_test_helper.cc
@@ -166,4 +166,11 @@ navigation->timestamp_ = timestamp; } +// static +void SerializedNavigationEntryTestHelper::SetReplacedEntryData( + const SerializedNavigationEntry::ReplacedNavigationEntryData& data, + SerializedNavigationEntry* navigation) { + navigation->replaced_entry_data_ = data; +} + } // namespace sessions
diff --git a/components/sessions/core/serialized_navigation_entry_test_helper.h b/components/sessions/core/serialized_navigation_entry_test_helper.h index c6f6475..dc057d5 100644 --- a/components/sessions/core/serialized_navigation_entry_test_helper.h +++ b/components/sessions/core/serialized_navigation_entry_test_helper.h
@@ -22,9 +22,6 @@ } namespace sessions { - -class SerializedNavigationEntry; - namespace test_data { extern const int kIndex; @@ -94,6 +91,10 @@ static void SetTimestamp(base::Time timestamp, SerializedNavigationEntry* navigation); + static void SetReplacedEntryData( + const SerializedNavigationEntry::ReplacedNavigationEntryData& data, + SerializedNavigationEntry* navigation); + private: DISALLOW_IMPLICIT_CONSTRUCTORS(SerializedNavigationEntryTestHelper); };
diff --git a/components/sessions/core/serialized_navigation_entry_unittest.cc b/components/sessions/core/serialized_navigation_entry_unittest.cc index 33c2275..7259287 100644 --- a/components/sessions/core/serialized_navigation_entry_unittest.cc +++ b/components/sessions/core/serialized_navigation_entry_unittest.cc
@@ -175,6 +175,33 @@ EXPECT_EQ(test_data::kRedirectURL1.spec(), sync_data.navigation_redirect(1).url()); EXPECT_FALSE(sync_data.has_last_navigation_redirect_url()); + EXPECT_FALSE(sync_data.has_replaced_navigation()); +} + +// Specifically test the |replaced_navigation| field, which should be populated +// when the navigation entry has been replaced by another entry (e.g. +// history.pushState()). +TEST(SerializedNavigationEntryTest, ReplacedNavigation) { + const GURL kReplacedURL = GURL("http://replaced-url.com"); + const int kReplacedTimestampMs = 79; + const ui::PageTransition kReplacedPageTransition = + ui::PAGE_TRANSITION_AUTO_BOOKMARK; + + SerializedNavigationEntry navigation = + SerializedNavigationEntryTestHelper::CreateNavigationForTest(); + SerializedNavigationEntryTestHelper::SetReplacedEntryData( + {kReplacedURL, syncer::ProtoTimeToTime(kReplacedTimestampMs), + kReplacedPageTransition}, + &navigation); + + const sync_pb::TabNavigation sync_data = navigation.ToSyncData(); + EXPECT_TRUE(sync_data.has_replaced_navigation()); + EXPECT_EQ(kReplacedURL.spec(), + sync_data.replaced_navigation().first_committed_url()); + EXPECT_EQ(kReplacedTimestampMs, + sync_data.replaced_navigation().first_timestamp_msec()); + EXPECT_EQ(sync_pb::SyncEnums_PageTransition_AUTO_BOOKMARK, + sync_data.replaced_navigation().first_page_transition()); } // Test that the last_navigation_redirect_url is set when needed. This test is
diff --git a/components/sync/protocol/proto_visitors.h b/components/sync/protocol/proto_visitors.h index 2bcd8f4..6838e9a 100644 --- a/components/sync/protocol/proto_visitors.h +++ b/components/sync/protocol/proto_visitors.h
@@ -599,6 +599,12 @@ VISIT(url); } +VISIT_PROTO_FIELDS(const sync_pb::ReplacedNavigation& proto) { + VISIT(first_committed_url); + VISIT(first_timestamp_msec); + VISIT_ENUM(first_page_transition); +} + VISIT_PROTO_FIELDS(const sync_pb::NigoriSpecifics& proto) { VISIT(encryption_keybag); VISIT(keybag_is_frozen); @@ -861,6 +867,7 @@ VISIT_ENUM(password_state); VISIT(task_id); VISIT_REP(ancestor_task_id); + VISIT(replaced_navigation); } VISIT_PROTO_FIELDS(const sync_pb::ThemeSpecifics& proto) {
diff --git a/components/sync/protocol/session_specifics.proto b/components/sync/protocol/session_specifics.proto index 0428b09..ced390a 100644 --- a/components/sync/protocol/session_specifics.proto +++ b/components/sync/protocol/session_specifics.proto
@@ -98,7 +98,7 @@ // frame. // optional string state = 5; // obsolete. // The core transition type. - optional SyncEnums.PageTransition page_transition = 6 [default = TYPED]; + optional SyncEnums.PageTransition page_transition = 6 [default = LINK]; // If this transition was triggered by a redirect, the redirect type. optional SyncEnums.PageTransitionRedirectType redirect_type = 7; // The unique navigation id (within this client). @@ -167,6 +167,12 @@ // B is got by clicking a link on page of A. This relationship is used to // define a Chrome Task as a tree rooted by a navigation. repeated int64 ancestor_task_id = 28; + + // When a history entry is replaced (e.g. history.replaceState()), this + // contains some information about the entry prior to being replaced. Even if + // an entry is replaced multiple times, it represents data prior to the + // *first* replace. + optional ReplacedNavigation replaced_navigation = 29; } // Navigation information for a single redirection within a single navigation. @@ -174,3 +180,12 @@ // A URL that redirected while navigating to the virtual_url. optional string url = 1; } + +// Subset of TabNavigation fields representing a navigation that was later +// replaced in history (e.g. history.replaceState()), which allows tracking +// information about the original navigation prior to the first replacement. +message ReplacedNavigation { + optional string first_committed_url = 1; + optional int64 first_timestamp_msec = 2; + optional SyncEnums.PageTransition first_page_transition = 3; +}
diff --git a/components/sync_sessions/sessions_sync_manager_unittest.cc b/components/sync_sessions/sessions_sync_manager_unittest.cc index 9e8b709..325edf7 100644 --- a/components/sync_sessions/sessions_sync_manager_unittest.cc +++ b/components/sync_sessions/sessions_sync_manager_unittest.cc
@@ -61,10 +61,7 @@ const base::Time kTime3 = base::Time::FromInternalValue(130); const base::Time kTime4 = base::Time::FromInternalValue(140); const base::Time kTime5 = base::Time::FromInternalValue(150); -const base::Time kTime6 = base::Time::FromInternalValue(160); -const base::Time kTime7 = base::Time::FromInternalValue(170); -const base::Time kTime8 = base::Time::FromInternalValue(180); -const base::Time kTime9 = base::Time::FromInternalValue(190); +const base::Time kTime6 = base::Time::FromInternalValue(190); std::string TabNodeIdToTag(const std::string& machine_tag, int tab_node_id) { return base::StringPrintf("%s %d", machine_tag.c_str(), tab_node_id); @@ -874,7 +871,7 @@ tab->set_current_entry_index(kNavs - 2); sessions::SessionTab session_tab; - manager()->SetSessionTabFromDelegate(*tab, kTime9, &session_tab); + manager()->SetSessionTabFromDelegate(*tab, kTime6, &session_tab); EXPECT_EQ(6, session_tab.current_navigation_index); ASSERT_EQ(8u, session_tab.navigations.size()); @@ -894,7 +891,7 @@ tab->set_current_entry_index(1); sessions::SessionTab session_tab; - manager()->SetSessionTabFromDelegate(*tab, kTime9, &session_tab); + manager()->SetSessionTabFromDelegate(*tab, kTime6, &session_tab); EXPECT_EQ(2, session_tab.current_navigation_index); ASSERT_EQ(3u, session_tab.navigations.size());
diff --git a/components/url_formatter/elide_url_unittest.cc b/components/url_formatter/elide_url_unittest.cc index 5e0384a..d403ce06 100644 --- a/components/url_formatter/elide_url_unittest.cc +++ b/components/url_formatter/elide_url_unittest.cc
@@ -347,15 +347,16 @@ kEllipsisStr + "berkeley.edu:4430/" + kEllipsisStr + "/arbitfilename"}, // Unescaping. - {"http://www/%E4%BD%A0%E5%A5%BD?q=%E4%BD%A0%E5%A5%BD#\xe4\xbd\xa0", - "www/\xe4\xbd\xa0\xe5\xa5\xbd?q=\xe4\xbd\xa0\xe5\xa5\xbd#" + + {"http://www/%E4%BD%A0%E5%A5%BD?" + "q=%E4%BD%A0%E5%A5%BD#\xe4\xbd\xa0\xe4\xbd\xa0\xe4\xbd\xa0", + "www/\xe4\xbd\xa0\xe5\xa5\xbd?q=\xe4\xbd\xa0\xe5\xa5\xbd#\xe4\xbd\xa0" + kEllipsisStr}, // Invalid unescaping for path. The ref will always be valid UTF-8. We // don't bother to do too many edge cases, since these are handled by the // escaper unittest. {"http://www/%E4%A0%E5%A5%BD?q=%E4%BD%A0%E5%A5%BD#\xe4\xbd\xa0", - "www/%E4%A0%E5%A5%BD?q=\xe4\xbd\xa0\xe5\xa5\xbd#" + kEllipsisStr}, + "www/%E4%A0%E5%A5%BD?q=\xe4\xbd\xa0\xe5\xa5\xbd#\xe4\xbd\xa0"}, }; RunElisionTest(testcases);
diff --git a/components/url_formatter/idn_spoof_checker.cc b/components/url_formatter/idn_spoof_checker.cc index a88c5e8f..aee748d 100644 --- a/components/url_formatter/idn_spoof_checker.cc +++ b/components/url_formatter/idn_spoof_checker.cc
@@ -110,8 +110,8 @@ // These Cyrillic letters look like Latin. A domain label entirely made of // these letters is blocked as a simplified whole-script-spoofable. - cyrillic_letters_latin_alike_ = - icu::UnicodeSet(icu::UnicodeString("[асԁеһіјӏорԛѕԝхуъЬҽпгѵѡ]"), status); + cyrillic_letters_latin_alike_ = icu::UnicodeSet( + icu::UnicodeString::fromUTF8("[асԁеһіјӏорԛѕԝхуъЬҽпгѵѡ]"), status); cyrillic_letters_latin_alike_.freeze(); cyrillic_letters_ = @@ -141,8 +141,8 @@ UParseError parse_error; diacritic_remover_.reset(icu::Transliterator::createFromRules( UNICODE_STRING_SIMPLE("DropAcc"), - icu::UnicodeString("::NFD; ::[:Nonspacing Mark:] Remove; ::NFC;" - " ł > l; ø > o; đ > d;"), + icu::UnicodeString::fromUTF8("::NFD; ::[:Nonspacing Mark:] Remove; ::NFC;" + " ł > l; ø > o; đ > d;"), UTRANS_FORWARD, parse_error, status)); // Supplement the Unicode confusable list by the following mapping. @@ -158,7 +158,7 @@ // - U+0D1F (ട) => s extra_confusable_mapper_.reset(icu::Transliterator::createFromRules( UNICODE_STRING_SIMPLE("ExtraConf"), - icu::UnicodeString( + icu::UnicodeString::fromUTF8( "ӏ > l; [кĸκ] > k; п > n; [ƅь] > b; в > b; м > m; н > h; " "т > t; [шщ] > w; ട > s;"), UTRANS_FORWARD, parse_error, status));
diff --git a/components/url_formatter/url_formatter.cc b/components/url_formatter/url_formatter.cc index d5c0d314..c422e3d 100644 --- a/components/url_formatter/url_formatter.cc +++ b/components/url_formatter/url_formatter.cc
@@ -586,11 +586,10 @@ NonHostComponentTransform(unescape_rules), &url_string, &new_parsed->query, adjustments); - // Ref. This is valid, unescaped UTF-8, so we can just convert. if (parsed.ref.is_valid()) url_string.push_back('#'); AppendFormattedComponent(spec, parsed.ref, - NonHostComponentTransform(net::UnescapeRule::NONE), + NonHostComponentTransform(unescape_rules), &url_string, &new_parsed->ref, adjustments); }
diff --git a/components/url_formatter/url_formatter_unittest.cc b/components/url_formatter/url_formatter_unittest.cc index 6fd3ece5..5aaf311 100644 --- a/components/url_formatter/url_formatter_unittest.cc +++ b/components/url_formatter/url_formatter_unittest.cc
@@ -828,7 +828,7 @@ {"With a port number and a reference", "http://www.google.com:8080/#\xE3\x82\xB0", default_format_type, - net::UnescapeRule::NORMAL, L"http://www.google.com:8080/#%E3%82%B0", 7}, + net::UnescapeRule::NORMAL, L"http://www.google.com:8080/#\x30B0", 7}, // -------- IDN tests -------- {"Japanese IDN with ja", "http://xn--l8jvb1ey91xtjb.jp", @@ -1119,7 +1119,7 @@ kFormatUrlOmitNothing, net::UnescapeRule::NORMAL, &parsed, nullptr, nullptr); EXPECT_EQ(WideToUTF16(L"http://\x30B0:\x30FC@\x30B0\x30FC\x30B0\x30EB.jp:8080" - L"/\x30B0/?q=\x30B0#%E3%82%B0"), + L"/\x30B0/?q=\x30B0#\x30B0"), formatted); EXPECT_EQ(WideToUTF16(L"\x30B0"), formatted.substr(parsed.username.begin, parsed.username.len)); @@ -1133,7 +1133,7 @@ formatted.substr(parsed.path.begin, parsed.path.len)); EXPECT_EQ(WideToUTF16(L"q=\x30B0"), formatted.substr(parsed.query.begin, parsed.query.len)); - EXPECT_EQ(WideToUTF16(L"%E3%82%B0"), + EXPECT_EQ(WideToUTF16(L"\x30B0"), formatted.substr(parsed.ref.begin, parsed.ref.len)); // Omit_username_password + unescape case. @@ -1143,7 +1143,7 @@ kFormatUrlOmitUsernamePassword, net::UnescapeRule::NORMAL, &parsed, nullptr, nullptr); EXPECT_EQ(WideToUTF16(L"http://\x30B0\x30FC\x30B0\x30EB.jp:8080" - L"/\x30B0/?q=\x30B0#%E3%82%B0"), + L"/\x30B0/?q=\x30B0#\x30B0"), formatted); EXPECT_FALSE(parsed.username.is_valid()); EXPECT_FALSE(parsed.password.is_valid()); @@ -1155,7 +1155,7 @@ formatted.substr(parsed.path.begin, parsed.path.len)); EXPECT_EQ(WideToUTF16(L"q=\x30B0"), formatted.substr(parsed.query.begin, parsed.query.len)); - EXPECT_EQ(WideToUTF16(L"%E3%82%B0"), + EXPECT_EQ(WideToUTF16(L"\x30B0"), formatted.substr(parsed.ref.begin, parsed.ref.len)); // View-source case. @@ -1389,9 +1389,12 @@ kFormatUrlOmitNothing, net::UnescapeRule::SPACES, unescape_offsets); const size_t ref_offsets[] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49}; + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, + 32, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, 33}; + // Unescape to "http://www.google.com/foo.html#\x30B0\x30B0z". CheckAdjustedOffsets("http://www.google.com/foo.html#%E3%82%B0%E3%82%B0z", kFormatUrlOmitNothing, net::UnescapeRule::NORMAL,
diff --git a/components/visitedlink/test/visitedlink_unittest.cc b/components/visitedlink/test/visitedlink_unittest.cc index 8686054..cde6fc1 100644 --- a/components/visitedlink/test/visitedlink_unittest.cc +++ b/components/visitedlink/test/visitedlink_unittest.cc
@@ -42,6 +42,10 @@ using content::MockRenderProcessHost; using content::RenderViewHostTester; +namespace content { +class SiteInstance; +} + namespace visitedlink { namespace { @@ -629,7 +633,8 @@ public: VisitedLinkRenderProcessHostFactory() : context_(new VisitCountingContext) {} content::RenderProcessHost* CreateRenderProcessHost( - content::BrowserContext* browser_context) const override { + content::BrowserContext* browser_context, + content::SiteInstance* site_instance) const override { return new VisitRelayingRenderProcessHost(browser_context, context_.get()); }
diff --git a/components/viz/common/gl_helper.cc b/components/viz/common/gl_helper.cc index bc4d27d..aabade3 100644 --- a/components/viz/common/gl_helper.cc +++ b/components/viz/common/gl_helper.cc
@@ -870,9 +870,7 @@ } void GLHelper::GenerateSyncToken(gpu::SyncToken* sync_token) { - const uint64_t fence_sync = gl_->InsertFenceSyncCHROMIUM(); - gl_->ShallowFlushCHROMIUM(); - gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token->GetData()); + gl_->GenSyncTokenCHROMIUM(sync_token->GetData()); } void GLHelper::WaitSyncToken(const gpu::SyncToken& sync_token) {
diff --git a/components/viz/common/yuv_readback_unittest.cc b/components/viz/common/yuv_readback_unittest.cc index 05753086..4f625e8 100644 --- a/components/viz/common/yuv_readback_unittest.cc +++ b/components/viz/common/yuv_readback_unittest.cc
@@ -358,11 +358,9 @@ gl_->GenMailboxCHROMIUM(mailbox.name); EXPECT_FALSE(mailbox.IsZero()); gl_->ProduceTextureDirectCHROMIUM(src_texture, mailbox.name); - const GLuint64 fence_sync = gl_->InsertFenceSyncCHROMIUM(); - gl_->ShallowFlushCHROMIUM(); gpu::SyncToken sync_token; - gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + gl_->GenSyncTokenCHROMIUM(sync_token.GetData()); std::string message = base::StringPrintf( "input size: %dx%d "
diff --git a/components/viz/host/DEPS b/components/viz/host/DEPS index 4087965f..a3a1c87 100644 --- a/components/viz/host/DEPS +++ b/components/viz/host/DEPS
@@ -9,6 +9,7 @@ "+mojo/public/cpp", "+services/viz/privileged/interfaces", "+services/viz/public/interfaces", + "+services/viz/public/interfaces/hit_test", ] specific_include_rules = {
diff --git a/components/viz/service/display/direct_renderer.cc b/components/viz/service/display/direct_renderer.cc index a8f5c80..6ba7ff7 100644 --- a/components/viz/service/display/direct_renderer.cc +++ b/components/viz/service/display/direct_renderer.cc
@@ -13,6 +13,7 @@ #include "base/containers/circular_deque.h" #include "base/metrics/histogram_macros.h" #include "base/numerics/safe_conversions.h" +#include "base/stl_util.h" #include "base/trace_event/trace_event.h" #include "cc/base/math_util.h" #include "cc/paint/filter_operations.h" @@ -675,4 +676,9 @@ current_frame_ = frame; } +bool DirectRenderer::HasAllocatedResourcesForTesting( + const RenderPassId& render_pass_id) const { + return IsRenderPassResourceAllocated(render_pass_id); +} + } // namespace viz
diff --git a/components/viz/service/display/direct_renderer.h b/components/viz/service/display/direct_renderer.h index ad832e2..f2498e80 100644 --- a/components/viz/service/display/direct_renderer.h +++ b/components/viz/service/display/direct_renderer.h
@@ -61,19 +61,11 @@ const gfx::Size& device_viewport_size); // Public interface implemented by subclasses. - virtual bool HasAllocatedResourcesForTesting( - const RenderPassId render_pass_id) const = 0; virtual void SwapBuffers(std::vector<ui::LatencyInfo> latency_info) = 0; virtual void SwapBuffersComplete() {} virtual void DidReceiveTextureInUseResponses( const gpu::TextureInUseResponses& responses) {} - // Allow tests to enlarge the texture size of non-root render passes to - // verify cases where the texture doesn't match the render pass size. - void SetEnlargePassTextureAmountForTesting(const gfx::Size& amount) { - enlarge_pass_texture_amount_ = amount; - } - // Public for tests that poke at internals. struct VIZ_SERVICE_EXPORT DrawingFrame { DrawingFrame(); @@ -95,6 +87,15 @@ DCLayerOverlayList dc_layer_overlay_list; }; + void SetCurrentFrameForTesting(const DrawingFrame& frame); + bool HasAllocatedResourcesForTesting( + const RenderPassId& render_pass_id) const; + // Allow tests to enlarge the texture size of non-root render passes to + // verify cases where the texture doesn't match the render pass size. + void SetEnlargePassTextureAmountForTesting(const gfx::Size& amount) { + enlarge_pass_texture_amount_ = amount; + } + protected: friend class BspWalkActionDrawPolygon; @@ -164,13 +165,13 @@ const base::flat_map<RenderPassId, RenderPassRequirements>& render_passes_in_frame) = 0; virtual void AllocateRenderPassResourceIfNeeded( - const RenderPassId render_pass_id, + const RenderPassId& render_pass_id, const gfx::Size& enlarged_size, ResourceTextureHint texturehint) = 0; virtual bool IsRenderPassResourceAllocated( - const RenderPassId render_pass_id) const = 0; - virtual const gfx::Size& GetRenderPassTextureSize( - const RenderPassId render_pass_id) = 0; + const RenderPassId& render_pass_id) const = 0; + virtual gfx::Size GetRenderPassTextureSize( + const RenderPassId& render_pass_id) = 0; virtual void BindFramebufferToOutputSurface() = 0; virtual void BindFramebufferToTexture(const RenderPassId render_pass_id) = 0; virtual void SetScissorTestRect(const gfx::Rect& scissor_rect) = 0; @@ -255,8 +256,6 @@ return ¤t_frame_; } - void SetCurrentFrameForTesting(const DrawingFrame& frame); - private: bool initialized_ = false; #if DCHECK_IS_ON()
diff --git a/components/viz/service/display/gl_renderer.cc b/components/viz/service/display/gl_renderer.cc index f22e8f28..f3bb5714 100644 --- a/components/viz/service/display/gl_renderer.cc +++ b/components/viz/service/display/gl_renderer.cc
@@ -3623,7 +3623,7 @@ } void GLRenderer::AllocateRenderPassResourceIfNeeded( - const RenderPassId render_pass_id, + const RenderPassId& render_pass_id, const gfx::Size& enlarged_size, ResourceTextureHint texturehint) { auto& resource = render_pass_textures_[render_pass_id]; @@ -3637,7 +3637,7 @@ } bool GLRenderer::IsRenderPassResourceAllocated( - const RenderPassId render_pass_id) const { + const RenderPassId& render_pass_id) const { auto texture_it = render_pass_textures_.find(render_pass_id); if (texture_it == render_pass_textures_.end()) return false; @@ -3647,17 +3647,11 @@ return texture->id() != 0; } -const gfx::Size& GLRenderer::GetRenderPassTextureSize( - const RenderPassId render_pass_id) { +gfx::Size GLRenderer::GetRenderPassTextureSize( + const RenderPassId& render_pass_id) { cc::ScopedResource* texture = render_pass_textures_[render_pass_id].get(); DCHECK(texture); return texture->size(); } -bool GLRenderer::HasAllocatedResourcesForTesting( - const RenderPassId render_pass_id) const { - auto iter = render_pass_textures_.find(render_pass_id); - return iter != render_pass_textures_.end() && iter->second->id(); -} - } // namespace viz
diff --git a/components/viz/service/display/gl_renderer.h b/components/viz/service/display/gl_renderer.h index d0a86aa..65472a3 100644 --- a/components/viz/service/display/gl_renderer.h +++ b/components/viz/service/display/gl_renderer.h
@@ -73,8 +73,6 @@ const gpu::TextureInUseResponses& responses) override; virtual bool IsContextLost(); - bool HasAllocatedResourcesForTesting( - const RenderPassId render_pass_id) const override; protected: void DidChangeVisibility() override; @@ -104,13 +102,13 @@ const base::flat_map<RenderPassId, RenderPassRequirements>& render_passes_in_frame) override; void AllocateRenderPassResourceIfNeeded( - const RenderPassId render_pass_id, + const RenderPassId& render_pass_id, const gfx::Size& enlarged_size, ResourceTextureHint texturehint) override; bool IsRenderPassResourceAllocated( - const RenderPassId render_pass_id) const override; - const gfx::Size& GetRenderPassTextureSize( - const RenderPassId render_pass_id) override; + const RenderPassId& render_pass_id) const override; + gfx::Size GetRenderPassTextureSize( + const RenderPassId& render_pass_id) override; void BindFramebufferToOutputSurface() override; void BindFramebufferToTexture(const RenderPassId render_pass_id) override; void SetScissorTestRect(const gfx::Rect& scissor_rect) override;
diff --git a/components/viz/service/display/gl_renderer_copier.cc b/components/viz/service/display/gl_renderer_copier.cc index a5d9bc2..5c04740 100644 --- a/components/viz/service/display/gl_renderer_copier.cc +++ b/components/viz/service/display/gl_renderer_copier.cc
@@ -438,10 +438,8 @@ gl->GenMailboxCHROMIUM(mailbox.name); gl->ProduceTextureDirectCHROMIUM(result_texture, mailbox.name); } - const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM(); - gl->ShallowFlushCHROMIUM(); gpu::SyncToken sync_token; - gl->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + gl->GenSyncTokenCHROMIUM(sync_token.GetData()); // Create a |release_callback| appropriate to the situation: If the // |result_texture| was provided in the mailbox of the copy request,
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index f550782..a0ef2d1 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -792,7 +792,7 @@ } void SkiaRenderer::AllocateRenderPassResourceIfNeeded( - const RenderPassId render_pass_id, + const RenderPassId& render_pass_id, const gfx::Size& enlarged_size, ResourceTextureHint texturehint) { #if BUILDFLAG(ENABLE_VULKAN) @@ -810,7 +810,7 @@ } bool SkiaRenderer::IsRenderPassResourceAllocated( - const RenderPassId render_pass_id) const { + const RenderPassId& render_pass_id) const { auto texture_it = render_pass_textures_.find(render_pass_id); if (texture_it == render_pass_textures_.end()) return false; @@ -820,17 +820,11 @@ return texture->id() != 0; } -const gfx::Size& SkiaRenderer::GetRenderPassTextureSize( - const RenderPassId render_pass_id) { +gfx::Size SkiaRenderer::GetRenderPassTextureSize( + const RenderPassId& render_pass_id) { cc::ScopedResource* texture = render_pass_textures_[render_pass_id].get(); DCHECK(texture); return texture->size(); } -bool SkiaRenderer::HasAllocatedResourcesForTesting( - const RenderPassId render_pass_id) const { - auto iter = render_pass_textures_.find(render_pass_id); - return iter != render_pass_textures_.end() && iter->second->id(); -} - } // namespace viz
diff --git a/components/viz/service/display/skia_renderer.h b/components/viz/service/display/skia_renderer.h index f7b8a4a..b2b2177a 100644 --- a/components/viz/service/display/skia_renderer.h +++ b/components/viz/service/display/skia_renderer.h
@@ -42,9 +42,6 @@ disable_picture_quad_image_filtering_ = disable; } - bool HasAllocatedResourcesForTesting( - const RenderPassId render_pass_id) const override; - protected: bool CanPartialSwap() override; ResourceFormat BackbufferFormat() const override; @@ -53,13 +50,13 @@ const base::flat_map<RenderPassId, RenderPassRequirements>& render_passes_in_frame) override; void AllocateRenderPassResourceIfNeeded( - const RenderPassId render_pass_id, + const RenderPassId& render_pass_id, const gfx::Size& enlarged_size, ResourceTextureHint texturehint) override; bool IsRenderPassResourceAllocated( - const RenderPassId render_pass_id) const override; - const gfx::Size& GetRenderPassTextureSize( - const RenderPassId render_pass_id) override; + const RenderPassId& render_pass_id) const override; + gfx::Size GetRenderPassTextureSize( + const RenderPassId& render_pass_id) override; void BindFramebufferToOutputSurface() override; void BindFramebufferToTexture(const RenderPassId render_pass_id) override; void SetScissorTestRect(const gfx::Rect& scissor_rect) override;
diff --git a/components/viz/service/display/software_renderer.cc b/components/viz/service/display/software_renderer.cc index 99727bfa..25370e807 100644 --- a/components/viz/service/display/software_renderer.cc +++ b/components/viz/service/display/software_renderer.cc
@@ -8,7 +8,6 @@ #include "base/trace_event/trace_event.h" #include "cc/base/math_util.h" #include "cc/paint/render_surface_filters.h" -#include "cc/resources/scoped_resource.h" #include "components/viz/common/display/renderer_settings.h" #include "components/viz/common/frame_sinks/copy_output_request.h" #include "components/viz/common/frame_sinks/copy_output_util.h" @@ -80,7 +79,6 @@ void SoftwareRenderer::FinishDrawingFrame() { TRACE_EVENT0("viz", "SoftwareRenderer::FinishDrawingFrame"); - current_framebuffer_lock_ = nullptr; current_framebuffer_canvas_.reset(); current_canvas_ = nullptr; root_canvas_ = nullptr; @@ -110,25 +108,17 @@ void SoftwareRenderer::BindFramebufferToOutputSurface() { DCHECK(!output_surface_->HasExternalStencilTest()); - current_framebuffer_lock_ = nullptr; current_framebuffer_canvas_.reset(); current_canvas_ = root_canvas_; } void SoftwareRenderer::BindFramebufferToTexture( const RenderPassId render_pass_id) { - cc::ScopedResource* texture = render_pass_textures_[render_pass_id].get(); - DCHECK(texture); - DCHECK(texture->id()); + auto it = render_pass_bitmaps_.find(render_pass_id); + DCHECK(it != render_pass_bitmaps_.end()); + SkBitmap& bitmap = it->second; - // Explicitly release lock, otherwise we can crash when try to lock - // same texture again. - current_framebuffer_lock_ = nullptr; - current_framebuffer_lock_ = - std::make_unique<cc::ResourceProvider::ScopedWriteLockSoftware>( - resource_provider_, texture->id()); - current_framebuffer_canvas_ = - std::make_unique<SkCanvas>(current_framebuffer_lock_->sk_bitmap()); + current_framebuffer_canvas_ = std::make_unique<SkCanvas>(bitmap); current_canvas_ = current_framebuffer_canvas_.get(); } @@ -453,16 +443,10 @@ } void SoftwareRenderer::DrawRenderPassQuad(const RenderPassDrawQuad* quad) { - cc::ScopedResource* content_texture = - render_pass_textures_[quad->render_pass_id].get(); - DCHECK(content_texture); - DCHECK(content_texture->id()); - DCHECK(IsSoftwareResource(content_texture->id())); - - cc::DisplayResourceProvider::ScopedReadLockSoftware lock( - resource_provider_, content_texture->id()); - if (!lock.valid()) + auto it = render_pass_bitmaps_.find(quad->render_pass_id); + if (it == render_pass_bitmaps_.end()) return; + SkBitmap& source_bitmap = it->second; SkRect dest_rect = gfx::RectFToSkRect(QuadVertexRect()); SkRect dest_visible_rect = @@ -471,22 +455,20 @@ gfx::RectF(quad->visible_rect))); SkRect content_rect = RectFToSkRect(quad->tex_coord_rect); - const SkBitmap* content = lock.sk_bitmap(); - sk_sp<SkImage> filter_image; const cc::FilterOperations* filters = FiltersForPass(quad->render_pass_id); if (filters) { DCHECK(!filters->IsEmpty()); auto paint_filter = cc::RenderSurfaceFilters::BuildImageFilter( - *filters, gfx::SizeF(content_texture->size())); + *filters, gfx::SizeF(source_bitmap.width(), source_bitmap.height())); auto image_filter = paint_filter ? paint_filter->cached_sk_filter_ : nullptr; if (image_filter) { SkIRect result_rect; // TODO(ajuma): Apply the filter in the same pass as the content where // possible (e.g. when there's no origin offset). See crbug.com/308201. - filter_image = - ApplyImageFilter(image_filter.get(), quad, *content, &result_rect); + filter_image = ApplyImageFilter(image_filter.get(), quad, source_bitmap, + &result_rect); if (result_rect.isEmpty()) { return; } @@ -508,7 +490,7 @@ sk_sp<SkShader> shader; if (!filter_image) { shader = - SkShader::MakeBitmapShader(*content, SkShader::kClamp_TileMode, + SkShader::MakeBitmapShader(source_bitmap, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &content_mat); } else { shader = filter_image->makeShader(SkShader::kClamp_TileMode, @@ -809,7 +791,7 @@ const base::flat_map<RenderPassId, RenderPassRequirements>& render_passes_in_frame) { std::vector<RenderPassId> passes_to_delete; - for (const auto& pair : render_pass_textures_) { + for (const auto& pair : render_pass_bitmaps_) { auto render_pass_it = render_passes_in_frame.find(pair.first); if (render_pass_it == render_passes_in_frame.end()) { passes_to_delete.push_back(pair.first); @@ -817,59 +799,56 @@ } gfx::Size required_size = render_pass_it->second.size; - ResourceTextureHint required_hint = render_pass_it->second.hint; - cc::ScopedResource* texture = pair.second.get(); - DCHECK(texture); + // The RenderPassRequirements have a hint, which is only used for gpu + // compositing so it is ignored here. + const SkBitmap& bitmap = pair.second; - bool size_appropriate = texture->size().width() >= required_size.width() && - texture->size().height() >= required_size.height(); - bool hint_appropriate = (texture->hint() & required_hint) == required_hint; - if (texture->id() && (!size_appropriate || !hint_appropriate)) - texture->Free(); + bool size_appropriate = bitmap.width() >= required_size.width() && + bitmap.height() >= required_size.height(); + if (!size_appropriate) + passes_to_delete.push_back(pair.first); } - // Delete RenderPass textures from the previous frame that will not be used + // Delete RenderPass bitmaps from the previous frame that will not be used // again. - for (size_t i = 0; i < passes_to_delete.size(); ++i) - render_pass_textures_.erase(passes_to_delete[i]); + for (const RenderPassId& id : passes_to_delete) + render_pass_bitmaps_.erase(id); } void SoftwareRenderer::AllocateRenderPassResourceIfNeeded( - const RenderPassId render_pass_id, + const RenderPassId& render_pass_id, const gfx::Size& enlarged_size, - ResourceTextureHint texturehint) { - auto& resource = render_pass_textures_[render_pass_id]; - if (resource && resource->id()) + ResourceTextureHint texture_hint) { + auto it = render_pass_bitmaps_.find(render_pass_id); + if (it != render_pass_bitmaps_.end()) return; - if (!resource) - resource = std::make_unique<cc::ScopedResource>(resource_provider_); - resource->Allocate(enlarged_size, texturehint, BackbufferFormat(), - current_frame()->current_render_pass->color_space); + // The |texture_hint| is only used for gpu-based rendering, so not used here. + // + // ColorSpace correctness for software compositing is a performance nightmare, + // so we don't do it. If we did, then the color space of the current frame's + // |current_render_pass| should be stored somewhere, but we should not set it + // on the bitmap itself. Instead, we'd use it with a SkColorSpaceXformCanvas + // that wraps the SkCanvas drawing into the bitmap. + SkImageInfo info = SkImageInfo::MakeN32( + enlarged_size.width(), enlarged_size.height(), kPremul_SkAlphaType); + SkBitmap bitmap; + bitmap.allocPixels(info); + render_pass_bitmaps_.emplace(render_pass_id, std::move(bitmap)); } bool SoftwareRenderer::IsRenderPassResourceAllocated( - const RenderPassId render_pass_id) const { - auto texture_it = render_pass_textures_.find(render_pass_id); - if (texture_it == render_pass_textures_.end()) - return false; - - cc::ScopedResource* texture = texture_it->second.get(); - DCHECK(texture); - return texture->id() != 0; + const RenderPassId& render_pass_id) const { + auto it = render_pass_bitmaps_.find(render_pass_id); + return it != render_pass_bitmaps_.end(); } -const gfx::Size& SoftwareRenderer::GetRenderPassTextureSize( - const RenderPassId render_pass_id) { - cc::ScopedResource* texture = render_pass_textures_[render_pass_id].get(); - DCHECK(texture); - return texture->size(); -} - -bool SoftwareRenderer::HasAllocatedResourcesForTesting( - const RenderPassId render_pass_id) const { - auto iter = render_pass_textures_.find(render_pass_id); - return iter != render_pass_textures_.end() && iter->second->id(); +gfx::Size SoftwareRenderer::GetRenderPassTextureSize( + const RenderPassId& render_pass_id) { + auto it = render_pass_bitmaps_.find(render_pass_id); + DCHECK(it != render_pass_bitmaps_.end()); + SkBitmap& bitmap = it->second; + return gfx::Size(bitmap.width(), bitmap.height()); } } // namespace viz
diff --git a/components/viz/service/display/software_renderer.h b/components/viz/service/display/software_renderer.h index 3d817fb4..6f007c2 100644 --- a/components/viz/service/display/software_renderer.h +++ b/components/viz/service/display/software_renderer.h
@@ -13,7 +13,6 @@ namespace cc { class OutputSurface; class DisplayResourceProvider; -class ScopedResource; } // namespace cc namespace viz { @@ -39,9 +38,6 @@ disable_picture_quad_image_filtering_ = disable; } - bool HasAllocatedResourcesForTesting( - const RenderPassId render_pass_id) const override; - protected: bool CanPartialSwap() override; ResourceFormat BackbufferFormat() const override; @@ -50,13 +46,13 @@ const base::flat_map<RenderPassId, RenderPassRequirements>& render_passes_in_frame) override; void AllocateRenderPassResourceIfNeeded( - const RenderPassId render_pass_id, + const RenderPassId& render_pass_id, const gfx::Size& enlarged_size, ResourceTextureHint texturehint) override; bool IsRenderPassResourceAllocated( - const RenderPassId render_pass_id) const override; - const gfx::Size& GetRenderPassTextureSize( - const RenderPassId render_pass_id) override; + const RenderPassId& render_pass_id) const override; + gfx::Size GetRenderPassTextureSize( + const RenderPassId& render_pass_id) override; void BindFramebufferToOutputSurface() override; void BindFramebufferToTexture(const RenderPassId render_pass_id) override; void SetScissorTestRect(const gfx::Rect& scissor_rect) override; @@ -103,9 +99,8 @@ const RenderPassDrawQuad* quad, SkShader::TileMode content_tile_mode) const; - // A map from RenderPass id to the texture used to draw the RenderPass from. - base::flat_map<RenderPassId, std::unique_ptr<cc::ScopedResource>> - render_pass_textures_; + // A map from RenderPass id to the bitmap used to draw the RenderPass from. + base::flat_map<RenderPassId, SkBitmap> render_pass_bitmaps_; bool disable_picture_quad_image_filtering_ = false; @@ -116,8 +111,6 @@ SkCanvas* root_canvas_ = nullptr; SkCanvas* current_canvas_ = nullptr; SkPaint current_paint_; - std::unique_ptr<cc::ResourceProvider::ScopedWriteLockSoftware> - current_framebuffer_lock_; std::unique_ptr<SkCanvas> current_framebuffer_canvas_; DISALLOW_COPY_AND_ASSIGN(SoftwareRenderer);
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index bf89326..19d34a9 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -176,6 +176,7 @@ "//ui/events:gesture_detection", "//ui/events/blink", "//ui/events/devices", + "//ui/events/gestures/blink", "//ui/gfx", "//ui/gfx/animation", "//ui/gfx/geometry", @@ -1787,6 +1788,7 @@ "renderer_host/p2p/socket_host_udp.h", "webrtc/webrtc_event_log_manager.cc", "webrtc/webrtc_event_log_manager.h", + "webrtc/webrtc_event_log_manager_common.h", "webrtc/webrtc_internals.cc", "webrtc/webrtc_internals.h", "webrtc/webrtc_internals_message_handler.cc", @@ -1794,6 +1796,8 @@ "webrtc/webrtc_internals_ui.cc", "webrtc/webrtc_internals_ui.h", "webrtc/webrtc_internals_ui_observer.h", + "webrtc/webrtc_local_event_log_manager.cc", + "webrtc/webrtc_local_event_log_manager.h", ] deps += [
diff --git a/content/browser/compositor/offscreen_browser_compositor_output_surface.cc b/content/browser/compositor/offscreen_browser_compositor_output_surface.cc index 6fc6604..f4775b4 100644 --- a/content/browser/compositor/offscreen_browser_compositor_output_surface.cc +++ b/content/browser/compositor/offscreen_browser_compositor_output_surface.cc
@@ -154,11 +154,9 @@ // (crbug.com/520567). // The original implementation had a flickering issue (crbug.com/515332). gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); - const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM(); - gl->ShallowFlushCHROMIUM(); gpu::SyncToken sync_token; - gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + gl->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); context_provider_->ContextSupport()->SignalSyncToken( sync_token, base::Bind(
diff --git a/content/browser/devtools/protocol/page_handler.cc b/content/browser/devtools/protocol/page_handler.cc index c46045be..d5b6c4f 100644 --- a/content/browser/devtools/protocol/page_handler.cc +++ b/content/browser/devtools/protocol/page_handler.cc
@@ -26,6 +26,7 @@ #include "content/browser/devtools/protocol/devtools_download_manager_helper.h" #include "content/browser/devtools/protocol/emulation_handler.h" #include "content/browser/frame_host/navigation_request.h" +#include "content/browser/manifest/manifest_manager_host.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/browser/web_contents/web_contents_impl.h" @@ -737,6 +738,18 @@ return Response::OK(); } +void PageHandler::GetAppManifest( + std::unique_ptr<GetAppManifestCallback> callback) { + WebContentsImpl* web_contents = GetWebContents(); + if (!web_contents || !web_contents->GetManifestManagerHost()) { + callback->sendFailure(Response::Error("Cannot retrieve manifest")); + return; + } + web_contents->GetManifestManagerHost()->RequestManifestDebugInfo( + base::BindOnce(&PageHandler::GotManifest, weak_factory_.GetWeakPtr(), + std::move(callback))); +} + WebContentsImpl* PageHandler::GetWebContents() { return host_ ? static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(host_)) : @@ -902,6 +915,30 @@ } } +void PageHandler::GotManifest(std::unique_ptr<GetAppManifestCallback> callback, + const GURL& manifest_url, + blink::mojom::ManifestDebugInfoPtr debug_info) { + std::unique_ptr<Array<Page::AppManifestError>> errors = + Array<Page::AppManifestError>::create(); + bool failed = true; + if (debug_info) { + failed = false; + for (const auto& error : debug_info->errors) { + errors->addItem(Page::AppManifestError::Create() + .SetMessage(error->message) + .SetCritical(error->critical) + .SetLine(error->line) + .SetColumn(error->column) + .Build()); + if (error->critical) + failed = true; + } + } + callback->sendSuccess( + manifest_url.possibly_invalid_spec(), std::move(errors), + failed ? Maybe<std::string>() : debug_info->raw_manifest); +} + Response PageHandler::StopLoading() { WebContentsImpl* web_contents = GetWebContents(); if (!web_contents)
diff --git a/content/browser/devtools/protocol/page_handler.h b/content/browser/devtools/protocol/page_handler.h index 6bf82dd..6c16bb2 100644 --- a/content/browser/devtools/protocol/page_handler.h +++ b/content/browser/devtools/protocol/page_handler.h
@@ -25,6 +25,7 @@ #include "content/public/browser/notification_registrar.h" #include "content/public/browser/readback_types.h" #include "content/public/common/javascript_dialog_type.h" +#include "third_party/WebKit/public/platform/modules/manifest/manifest_manager.mojom.h" #include "url/gurl.h" class SkBitmap; @@ -136,6 +137,9 @@ Response SetDownloadBehavior(const std::string& behavior, Maybe<std::string> download_path) override; + void GetAppManifest( + std::unique_ptr<GetAppManifestCallback> callback) override; + private: enum EncodingFormat { PNG, JPEG }; @@ -158,6 +162,10 @@ const blink::WebDeviceEmulationParams& original_params, const gfx::Image& image); + void GotManifest(std::unique_ptr<GetAppManifestCallback> callback, + const GURL& manifest_url, + blink::mojom::ManifestDebugInfoPtr debug_info); + // NotificationObserver overrides. void Observe(int type, const NotificationSource& source,
diff --git a/content/browser/devtools/protocol/storage_handler.cc b/content/browser/devtools/protocol/storage_handler.cc index 4e2b2e3..a988775a 100644 --- a/content/browser/devtools/protocol/storage_handler.cc +++ b/content/browser/devtools/protocol/storage_handler.cc
@@ -263,18 +263,21 @@ cache_storage_observer_.release()); } if (indexed_db_observer_) { - indexed_db_observer_->TaskRunner()->DeleteSoon( - FROM_HERE, std::move(indexed_db_observer_)); + scoped_refptr<base::SequencedTaskRunner> observer_task_runner = + indexed_db_observer_->TaskRunner(); + observer_task_runner->DeleteSoon(FROM_HERE, + std::move(indexed_db_observer_)); } return Response::OK(); } -Response StorageHandler::ClearDataForOrigin( +void StorageHandler::ClearDataForOrigin( const std::string& origin, - const std::string& storage_types) { + const std::string& storage_types, + std::unique_ptr<ClearDataForOriginCallback> callback) { if (!process_) - return Response::InternalError(); + return callback->sendFailure(Response::InternalError()); StoragePartition* partition = process_->GetStoragePartition(); std::vector<std::string> types = base::SplitString( @@ -302,13 +305,17 @@ if (set.count(Storage::StorageTypeEnum::All)) remove_mask |= StoragePartition::REMOVE_DATA_MASK_ALL; - if (!remove_mask) - return Response::InvalidParams("No valid storage type specified"); + if (!remove_mask) { + return callback->sendFailure( + Response::InvalidParams("No valid storage type specified")); + } - partition->ClearDataForOrigin( - remove_mask, StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, - GURL(origin)); - return Response::OK(); + partition->ClearData(remove_mask, + StoragePartition::QUOTA_MANAGED_STORAGE_MASK_ALL, + GURL(origin), StoragePartition::OriginMatcherFunction(), + base::Time(), base::Time::Max(), + base::BindOnce(&ClearDataForOriginCallback::sendSuccess, + std::move(callback))); } void StorageHandler::GetUsageAndQuota(
diff --git a/content/browser/devtools/protocol/storage_handler.h b/content/browser/devtools/protocol/storage_handler.h index a3f305c..dc33e45 100644 --- a/content/browser/devtools/protocol/storage_handler.h +++ b/content/browser/devtools/protocol/storage_handler.h
@@ -32,9 +32,10 @@ Response Disable() override; // content::protocol::storage::Backend - Response ClearDataForOrigin( + void ClearDataForOrigin( const std::string& origin, - const std::string& storage_types) override; + const std::string& storage_types, + std::unique_ptr<ClearDataForOriginCallback> callback) override; void GetUsageAndQuota( const String& origin, std::unique_ptr<GetUsageAndQuotaCallback> callback) override;
diff --git a/content/browser/devtools/protocol_config.json b/content/browser/devtools/protocol_config.json index 480a81f0..dcd6a6f 100644 --- a/content/browser/devtools/protocol_config.json +++ b/content/browser/devtools/protocol_config.json
@@ -48,9 +48,9 @@ "domain": "Page", "include": ["enable", "disable", "reload", "navigate", "stopLoading", "getNavigationHistory", "navigateToHistoryEntry", "captureScreenshot", "startScreencast", "stopScreencast", "screencastFrameAck", "handleJavaScriptDialog", "setColorPickerEnabled", "requestAppBanner", - "printToPDF", "bringToFront", "setDownloadBehavior"], + "printToPDF", "bringToFront", "setDownloadBehavior", "getAppManifest"], "include_events": ["colorPicked", "interstitialShown", "interstitialHidden", "javascriptDialogOpening", "javascriptDialogClosed", "screencastVisibilityChanged", "screencastFrame"], - "async": ["captureScreenshot", "printToPDF", "navigate"] + "async": ["captureScreenshot", "printToPDF", "navigate", "getAppManifest"] }, { "domain": "Runtime", @@ -69,7 +69,7 @@ }, { "domain": "Storage", - "async": ["getUsageAndQuota"] + "async": ["getUsageAndQuota", "clearDataForOrigin"] }, { "domain": "SystemInfo",
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc index 7b4b1f1..1b8d347 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.cc +++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -1232,6 +1232,8 @@ } std::string RenderFrameDevToolsAgentHost::GetOpenerId() { + if (!frame_tree_node_) + return std::string(); FrameTreeNode* opener = frame_tree_node_->original_opener(); return opener ? opener->devtools_frame_token().ToString() : std::string(); }
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc index 1a0255a..90d1cb6 100644 --- a/content/browser/frame_host/navigation_controller_impl.cc +++ b/content/browser/frame_host/navigation_controller_impl.cc
@@ -71,6 +71,7 @@ #include "content/public/browser/notification_types.h" #include "content/public/browser/render_widget_host.h" #include "content/public/browser/render_widget_host_view.h" +#include "content/public/browser/replaced_navigation_entry_data.h" #include "content/public/browser/storage_partition.h" #include "content/public/common/content_client.h" #include "content/public/common/content_constants.h" @@ -163,6 +164,23 @@ return false; } +// See replaced_navigation_entry_data.h for details: this information is meant +// to ensure |*output_entry| keeps track of its original URL (landing page in +// case of server redirects) as it gets replaced (e.g. history.replaceState()), +// without overwriting it later, for main frames. +void CopyReplacedNavigationEntryDataIfPreviouslyEmpty( + const NavigationEntryImpl& replaced_entry, + NavigationEntryImpl* output_entry) { + if (output_entry->GetReplacedEntryData().has_value()) + return; + + ReplacedNavigationEntryData data; + data.first_committed_url = replaced_entry.GetURL(); + data.first_timestamp = replaced_entry.GetTimestamp(); + data.first_transition_type = replaced_entry.GetTransitionType(); + output_entry->SetReplacedEntryData(data); +} + } // namespace // NavigationControllerImpl ---------------------------------------------------- @@ -1331,6 +1349,14 @@ // which land us at the last committed entry. entry = GetLastCommittedEntry(); + // TODO(crbug.com/751023): Set page transition type to PAGE_TRANSITION_LINK + // to avoid misleading interpretations (e.g. URLs paired with + // PAGE_TRANSITION_TYPED that haven't actually been typed) as well as to fix + // the inconsistency with what we report to observers (PAGE_TRANSITION_LINK + // | PAGE_TRANSITION_CLIENT_REDIRECT). + + CopyReplacedNavigationEntryDataIfPreviouslyEmpty(*entry, entry); + // If this is a same document navigation, then there's no SSLStatus in the // NavigationHandle so don't overwrite the existing entry's SSLStatus. if (!is_same_document) @@ -1463,6 +1489,12 @@ DCHECK(GetLastCommittedEntry()) << "ClassifyNavigation should guarantee " << "that a last committed entry exists."; + // The DCHECK below documents the fact that we don't know of any situation + // where |replace_entry| is true for subframe navigations. This simplifies + // reasoning about the replacement struct for subframes (see + // CopyReplacedNavigationEntryDataIfPreviouslyEmpty()). + DCHECK(!replace_entry); + // Make sure we don't leak frame_entry if new_entry doesn't take ownership. scoped_refptr<FrameNavigationEntry> frame_entry(new FrameNavigationEntry( rfh->frame_tree_node()->unique_name(), params.item_sequence_number, @@ -1874,6 +1906,8 @@ // When replacing, don't prune the forward history. if (replace && current_size > 0) { + CopyReplacedNavigationEntryDataIfPreviouslyEmpty( + *entries_[last_committed_entry_index_], entry.get()); entries_[last_committed_entry_index_] = std::move(entry); return; }
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc index 3bf2fb8..3be2bdc 100644 --- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc +++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -67,6 +67,9 @@ "var f = document.querySelector('iframe');" "f.parentNode.removeChild(f);"; +using testing::ElementsAre; +using testing::IsEmpty; + } // namespace namespace content { @@ -4016,6 +4019,436 @@ testing::HasSubstr("dynamicFrame")); } +// Verify that navigations caused by client-side redirects populates the entry's +// replaced data. +IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, + ReplacedNavigationEntryData_ClientSideRedirect) { + FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetFrameTree() + ->root(); + const NavigationControllerImpl& controller = + static_cast<const NavigationControllerImpl&>( + shell()->web_contents()->GetController()); + GURL url1(embedded_test_server()->GetURL( + "/navigation_controller/client_redirect.html")); + GURL url2(embedded_test_server()->GetURL( + "/navigation_controller/simple_page_1.html")); + + { + // Load the redirecting page. + FrameNavigateParamsCapturer capturer(root); + capturer.set_navigations_remaining(2); + ASSERT_TRUE(NavigateToURL(shell(), url1)); + capturer.Wait(); + + ASSERT_EQ(1, controller.GetEntryCount()); + NavigationEntry* entry1 = controller.GetEntryAtIndex(0); + ASSERT_EQ(url2, entry1->GetURL()); + ASSERT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs( + entry1->GetTransitionType(), + ui::PageTransitionFromInt(ui::PAGE_TRANSITION_LINK | + ui::PAGE_TRANSITION_CLIENT_REDIRECT))); + + ASSERT_TRUE(entry1->GetReplacedEntryData().has_value()); + EXPECT_EQ(url1, entry1->GetReplacedEntryData()->first_committed_url); + EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs( + entry1->GetReplacedEntryData()->first_transition_type, + ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | + ui::PAGE_TRANSITION_FROM_ADDRESS_BAR))) + << base::StringPrintf( + "%X", entry1->GetReplacedEntryData()->first_transition_type); + } +} + +// Verify that navigations caused by location.replace() populates the entry's +// replaced data. +IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, + ReplacedNavigationEntryData_LocationReplace) { + FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetFrameTree() + ->root(); + const NavigationControllerImpl& controller = + static_cast<const NavigationControllerImpl&>( + shell()->web_contents()->GetController()); + GURL url1(embedded_test_server()->GetURL( + "/navigation_controller/simple_page_1.html")); + GURL url2(embedded_test_server()->GetURL( + "/navigation_controller/simple_page_2.html")); + + // Test fixture: start with typing a URL. + { + ASSERT_TRUE(NavigateToURL(shell(), url1)); + ASSERT_EQ(1, controller.GetEntryCount()); + NavigationEntry* entry1 = controller.GetEntryAtIndex(0); + ASSERT_EQ(url1, entry1->GetURL()); + ASSERT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs( + entry1->GetTransitionType(), + ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | + ui::PAGE_TRANSITION_FROM_ADDRESS_BAR))); + EXPECT_FALSE(entry1->GetReplacedEntryData().has_value()); + } + + const base::Time time1 = controller.GetEntryAtIndex(0)->GetTimestamp(); + + { + // location.replace(). + FrameNavigateParamsCapturer capturer(root); + std::string script = "location.replace('" + url2.spec() + "')"; + EXPECT_TRUE(ExecuteScript(root, script)); + capturer.Wait(); + + ASSERT_EQ(1, controller.GetEntryCount()); + NavigationEntry* entry1 = controller.GetEntryAtIndex(0); + ASSERT_EQ(url2, entry1->GetURL()); + ASSERT_NE(time1, entry1->GetTimestamp()); + + ASSERT_TRUE(entry1->GetReplacedEntryData().has_value()); + EXPECT_EQ(url1, entry1->GetReplacedEntryData()->first_committed_url); + EXPECT_EQ(time1, entry1->GetReplacedEntryData()->first_timestamp); + EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs( + entry1->GetReplacedEntryData()->first_transition_type, + ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | + ui::PAGE_TRANSITION_FROM_ADDRESS_BAR))); + } +} + +// Verify that history.replaceState() populates the navigation entry's replaced +// entry data. +IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, + ReplacedNavigationEntryData_ReplaceState) { + FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetFrameTree() + ->root(); + const NavigationControllerImpl& controller = + static_cast<const NavigationControllerImpl&>( + shell()->web_contents()->GetController()); + GURL url1(embedded_test_server()->GetURL( + "/navigation_controller/simple_page_1.html")); + GURL url2(embedded_test_server()->GetURL( + "/navigation_controller/simple_page_2.html")); + GURL url3(embedded_test_server()->GetURL( + "/navigation_controller/simple_page_3.html")); + + // Test fixture: start with typing a URL. + { + ASSERT_TRUE(NavigateToURL(shell(), url1)); + ASSERT_EQ(1, controller.GetEntryCount()); + NavigationEntry* entry1 = controller.GetEntryAtIndex(0); + ASSERT_EQ(url1, entry1->GetURL()); + ASSERT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs( + entry1->GetTransitionType(), + ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | + ui::PAGE_TRANSITION_FROM_ADDRESS_BAR))); + EXPECT_FALSE(entry1->GetReplacedEntryData().has_value()); + } + + const base::Time time1 = controller.GetEntryAtIndex(0)->GetTimestamp(); + + { + // history.replaceState(). + FrameNavigateParamsCapturer capturer(root); + std::string script = + "history.replaceState({}, 'page 2', 'simple_page_2.html')"; + ASSERT_TRUE(ExecuteScript(root, script)); + capturer.Wait(); + + ASSERT_EQ(1, controller.GetEntryCount()); + NavigationEntry* entry1 = controller.GetEntryAtIndex(0); + ASSERT_EQ(url2, entry1->GetURL()); + ASSERT_NE(time1, entry1->GetTimestamp()); + + ASSERT_TRUE(entry1->GetReplacedEntryData().has_value()); + EXPECT_EQ(url1, entry1->GetReplacedEntryData()->first_committed_url); + EXPECT_EQ(time1, entry1->GetReplacedEntryData()->first_timestamp); + EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs( + entry1->GetReplacedEntryData()->first_transition_type, + ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | + ui::PAGE_TRANSITION_FROM_ADDRESS_BAR))); + } + + { + // Reload from the renderer side and make sure the replaced entry data + // doesn't change. + FrameNavigateParamsCapturer capturer(root); + ASSERT_TRUE(ExecuteScript(root, "location.reload()")); + capturer.Wait(); + + ASSERT_EQ(1, controller.GetEntryCount()); + NavigationEntry* entry1 = controller.GetEntryAtIndex(0); + ASSERT_EQ(url2, entry1->GetURL()); + ASSERT_NE(time1, entry1->GetTimestamp()); + + ASSERT_TRUE(entry1->GetReplacedEntryData().has_value()); + EXPECT_EQ(url1, entry1->GetReplacedEntryData()->first_committed_url); + EXPECT_EQ(time1, entry1->GetReplacedEntryData()->first_timestamp); + EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs( + entry1->GetReplacedEntryData()->first_transition_type, + ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | + ui::PAGE_TRANSITION_FROM_ADDRESS_BAR))); + } + + { + // history.replaceState(). + FrameNavigateParamsCapturer capturer(root); + std::string script = + "history.replaceState({}, 'page 3', 'simple_page_3.html')"; + ASSERT_TRUE(ExecuteScript(root, script)); + capturer.Wait(); + + ASSERT_EQ(1, controller.GetEntryCount()); + NavigationEntry* entry1 = controller.GetEntryAtIndex(0); + ASSERT_EQ(url3, entry1->GetURL()); + ASSERT_NE(time1, entry1->GetTimestamp()); + + ASSERT_TRUE(entry1->GetReplacedEntryData().has_value()); + EXPECT_EQ(url1, entry1->GetReplacedEntryData()->first_committed_url); + EXPECT_EQ(time1, entry1->GetReplacedEntryData()->first_timestamp); + EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs( + entry1->GetReplacedEntryData()->first_transition_type, + ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | + ui::PAGE_TRANSITION_FROM_ADDRESS_BAR))); + } +} + +// Verify that history.pushState() does not populate the navigation entry's +// replaced entry data. +IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, + ReplacedNavigationEntryData_PushState) { + FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetFrameTree() + ->root(); + const NavigationControllerImpl& controller = + static_cast<const NavigationControllerImpl&>( + shell()->web_contents()->GetController()); + GURL url1(embedded_test_server()->GetURL( + "/navigation_controller/simple_page_1.html")); + GURL url2(embedded_test_server()->GetURL( + "/navigation_controller/simple_page_2.html")); + + // Test fixture: start with typing a URL. + { + ASSERT_TRUE(NavigateToURL(shell(), url1)); + ASSERT_EQ(1, controller.GetEntryCount()); + NavigationEntry* entry1 = controller.GetEntryAtIndex(0); + ASSERT_EQ(url1, entry1->GetURL()); + ASSERT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs( + entry1->GetTransitionType(), + ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | + ui::PAGE_TRANSITION_FROM_ADDRESS_BAR))); + EXPECT_FALSE(entry1->GetReplacedEntryData().has_value()); + } + + { + // history.pushState(). + FrameNavigateParamsCapturer capturer(root); + std::string script = + "history.pushState({}, 'page 2', 'simple_page_2.html')"; + ASSERT_TRUE(ExecuteScript(root, script)); + capturer.Wait(); + + ASSERT_EQ(2, controller.GetEntryCount()); + ASSERT_EQ(url1, controller.GetEntryAtIndex(0)->GetURL()); + ASSERT_EQ(url2, controller.GetEntryAtIndex(1)->GetURL()); + + EXPECT_FALSE( + controller.GetEntryAtIndex(0)->GetReplacedEntryData().has_value()); + EXPECT_FALSE( + controller.GetEntryAtIndex(1)->GetReplacedEntryData().has_value()); + } +} + +// Verify that location.reload() does not populate the navigation entry's +// replaced entry data. +IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, + ReplacedNavigationEntryData_LocationReload) { + FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetFrameTree() + ->root(); + const NavigationControllerImpl& controller = + static_cast<const NavigationControllerImpl&>( + shell()->web_contents()->GetController()); + GURL url1(embedded_test_server()->GetURL( + "/navigation_controller/simple_page_1.html")); + + // Test fixture: start with typing a URL. + { + ASSERT_TRUE(NavigateToURL(shell(), url1)); + ASSERT_EQ(1, controller.GetEntryCount()); + NavigationEntry* entry1 = controller.GetEntryAtIndex(0); + ASSERT_EQ(url1, entry1->GetURL()); + ASSERT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs( + entry1->GetTransitionType(), + ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | + ui::PAGE_TRANSITION_FROM_ADDRESS_BAR))); + EXPECT_FALSE(entry1->GetReplacedEntryData().has_value()); + } + + const base::Time time1 = controller.GetEntryAtIndex(0)->GetTimestamp(); + + { + // Reload from the renderer side and make sure replaced entry data is not + // stored. + FrameNavigateParamsCapturer capturer(root); + ASSERT_TRUE(ExecuteScript(root, "location.reload()")); + capturer.Wait(); + + ASSERT_EQ(1, controller.GetEntryCount()); + NavigationEntry* entry1 = controller.GetEntryAtIndex(0); + ASSERT_EQ(url1, entry1->GetURL()); + ASSERT_NE(time1, entry1->GetTimestamp()); + + // At least the timestamp has changed, so we need to keep a copy of the + // replaced data. + ASSERT_TRUE(entry1->GetReplacedEntryData().has_value()); + EXPECT_EQ(url1, entry1->GetReplacedEntryData()->first_committed_url); + EXPECT_EQ(time1, entry1->GetReplacedEntryData()->first_timestamp); + EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs( + entry1->GetReplacedEntryData()->first_transition_type, + ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | + ui::PAGE_TRANSITION_FROM_ADDRESS_BAR))); + } +} + +// Verify the scenario where the user goes back to a navigatin entry that had +// previously replaced it's URL (via history.replaceState()), for a URL that +// (if fetched) causes a server-side redirect. In this scenario, the fact of +// going back should not influence the replaced data, and hence the first URL +// prior to history.replaceState() should remain set. +IN_PROC_BROWSER_TEST_F( + NavigationControllerBrowserTest, + ReplacedNavigationEntryData_BackAfterReplaceStateWithRedirect) { + FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetFrameTree() + ->root(); + const NavigationControllerImpl& controller = + static_cast<const NavigationControllerImpl&>( + shell()->web_contents()->GetController()); + GURL url1(embedded_test_server()->GetURL( + "/navigation_controller/simple_page_1.html")); + GURL url2(embedded_test_server()->GetURL( + "/navigation_controller/simple_page_2.html")); + GURL redirecting_url_to_url2( + embedded_test_server()->GetURL("/server-redirect?" + url2.spec())); + GURL url3(embedded_test_server()->GetURL("/simple_page.html")); + + // Start with typing a URL. + { + ASSERT_TRUE(NavigateToURL(shell(), url1)); + ASSERT_EQ(1, controller.GetEntryCount()); + NavigationEntry* entry1 = controller.GetEntryAtIndex(0); + ASSERT_EQ(url1, entry1->GetURL()); + ASSERT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs( + entry1->GetTransitionType(), + ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | + ui::PAGE_TRANSITION_FROM_ADDRESS_BAR))); + EXPECT_FALSE(entry1->GetReplacedEntryData().has_value()); + } + + { + // history.replaceState(), pointing to a URL that would redirect to |url2|. + FrameNavigateParamsCapturer capturer(root); + std::string script = "history.replaceState({}, 'page 2', '" + + redirecting_url_to_url2.spec() + "')"; + + ASSERT_TRUE(ExecuteScript(root, script)); + capturer.Wait(); + + ASSERT_EQ(1, controller.GetEntryCount()); + NavigationEntry* entry1 = controller.GetEntryAtIndex(0); + ASSERT_EQ(redirecting_url_to_url2, entry1->GetURL()); + ASSERT_TRUE(entry1->GetReplacedEntryData().has_value()); + ASSERT_EQ(url1, entry1->GetReplacedEntryData()->first_committed_url); + } + + // Type another URL, |url3|. + { + ASSERT_TRUE(NavigateToURL(shell(), url3)); + ASSERT_EQ(2, controller.GetEntryCount()); + } + + // Back, which should redirect to |url2|. + { + FrameNavigateParamsCapturer capturer(root); + shell()->web_contents()->GetController().GoBack(); + capturer.Wait(); + + NavigationEntry* entry1 = controller.GetEntryAtIndex(0); + ASSERT_EQ(url2, entry1->GetURL()); + + // We still expect |url1| in the replaced data. + ASSERT_TRUE(entry1->GetReplacedEntryData().has_value()); + EXPECT_EQ(url1, entry1->GetReplacedEntryData()->first_committed_url); + } +} + +// Verify that navigating back in history does not populate the navigation +// entry's replaced entry data. +IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, + ReplacedNavigationEntryData_Back) { + FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetFrameTree() + ->root(); + const NavigationControllerImpl& controller = + static_cast<const NavigationControllerImpl&>( + shell()->web_contents()->GetController()); + GURL url1(embedded_test_server()->GetURL( + "/navigation_controller/simple_page_1.html")); + GURL url2(embedded_test_server()->GetURL( + "/navigation_controller/simple_page_2.html")); + + // Test fixture: start with typing two URLs. + { + ASSERT_TRUE(NavigateToURL(shell(), url1)); + ASSERT_TRUE(NavigateToURL(shell(), url2)); + ASSERT_EQ(2, controller.GetEntryCount()); + NavigationEntry* entry1 = controller.GetEntryAtIndex(0); + NavigationEntry* entry2 = controller.GetEntryAtIndex(1); + ASSERT_EQ(url1, entry1->GetURL()); + ASSERT_EQ(url2, entry2->GetURL()); + ASSERT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs( + entry1->GetTransitionType(), + ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | + ui::PAGE_TRANSITION_FROM_ADDRESS_BAR))); + ASSERT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs( + entry2->GetTransitionType(), + ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | + ui::PAGE_TRANSITION_FROM_ADDRESS_BAR))); + EXPECT_FALSE(entry1->GetReplacedEntryData().has_value()); + EXPECT_FALSE(entry2->GetReplacedEntryData().has_value()); + } + + const base::Time time1 = controller.GetEntryAtIndex(0)->GetTimestamp(); + + { + // Back. + FrameNavigateParamsCapturer capturer(root); + shell()->web_contents()->GetController().GoBack(); + capturer.Wait(); + + // Assertions below document the current behavior. + NavigationEntry* entry1 = controller.GetEntryAtIndex(0); + NavigationEntry* entry2 = controller.GetEntryAtIndex(1); + ASSERT_EQ(url1, entry1->GetURL()); + ASSERT_NE(time1, entry1->GetTimestamp()); + ASSERT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs( + entry1->GetTransitionType(), + ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | + ui::PAGE_TRANSITION_FROM_ADDRESS_BAR | + ui::PAGE_TRANSITION_FORWARD_BACK))); + ASSERT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs( + entry2->GetTransitionType(), + ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | + ui::PAGE_TRANSITION_FROM_ADDRESS_BAR))); + + // It is questionable whether a copy of the replaced data should be made + // here too, because of the modified timestamp as well as the new qualifier, + // ui::PAGE_TRANSITION_FORWARD_BACK. However, we've decided against since + // there is no actual replacement happening. + EXPECT_FALSE(entry1->GetReplacedEntryData().has_value()); + EXPECT_FALSE(entry2->GetReplacedEntryData().has_value()); + } +} + // Ensure we don't crash when cloning a named window. This happened in // https://crbug.com/603245 because neither the FrameTreeNode ID nor the name of // the cloned window matched the root FrameNavigationEntry.
diff --git a/content/browser/frame_host/navigation_entry_impl.cc b/content/browser/frame_host/navigation_entry_impl.cc index 20bb33c..4d7272e 100644 --- a/content/browser/frame_host/navigation_entry_impl.cc +++ b/content/browser/frame_host/navigation_entry_impl.cc
@@ -556,6 +556,11 @@ return root_node()->frame_entry->redirect_chain(); } +const base::Optional<ReplacedNavigationEntryData>& +NavigationEntryImpl::GetReplacedEntryData() const { + return replaced_entry_data_; +} + bool NavigationEntryImpl::IsRestored() const { return restore_type_ != RestoreType::NONE; } @@ -652,6 +657,7 @@ #endif // ResetForCommit: reload_type_ copy->extra_data_ = extra_data_; + copy->replaced_entry_data_ = replaced_entry_data_; return copy; }
diff --git a/content/browser/frame_host/navigation_entry_impl.h b/content/browser/frame_host/navigation_entry_impl.h index fc75a4be..6d54c4b 100644 --- a/content/browser/frame_host/navigation_entry_impl.h +++ b/content/browser/frame_host/navigation_entry_impl.h
@@ -14,6 +14,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/optional.h" #include "base/time/time.h" #include "build/build_config.h" #include "content/browser/frame_host/frame_navigation_entry.h" @@ -24,6 +25,7 @@ #include "content/public/browser/global_request_id.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/reload_type.h" +#include "content/public/browser/replaced_navigation_entry_data.h" #include "content/public/browser/restore_type.h" #include "content/public/browser/ssl_status.h" #include "content/public/common/page_state.h" @@ -147,6 +149,8 @@ int GetHttpStatusCode() const override; void SetRedirectChain(const std::vector<GURL>& redirects) override; const std::vector<GURL>& GetRedirectChain() const override; + const base::Optional<ReplacedNavigationEntryData>& GetReplacedEntryData() + const override; bool IsRestored() const override; std::string GetExtraHeaders() const override; void AddExtraHeaders(const std::string& extra_headers) override; @@ -424,6 +428,12 @@ } #endif + // Stores a record of the what was committed in this NavigationEntry's main + // frame before it was replaced (e.g. by history.replaceState()). + void SetReplacedEntryData(const ReplacedNavigationEntryData& data) { + replaced_entry_data_ = data; + } + private: // WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING // Session/Tab restore save portions of this class so that it can be recreated @@ -560,6 +570,13 @@ // for a pending navigation. Defaults to false. bool ssl_error_; + // Stores information about the entry prior to being replaced (e.g. + // history.replaceState()). It is preserved after commit (session sync for + // offline analysis) but should not be persisted. The concept is valid for + // subframe navigations but we only need to track it for main frames, that's + // why the field is listed here. + base::Optional<ReplacedNavigationEntryData> replaced_entry_data_; + DISALLOW_COPY_AND_ASSIGN(NavigationEntryImpl); };
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index c74b086..31988e64 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -3707,10 +3707,11 @@ remote_interfaces_->Bind(std::move(remote_interfaces)); if (base::FeatureList::IsEnabled(features::kMojoInputMessages)) { - GetRemoteInterfaces()->GetInterface(&frame_input_handler_); + remote_interfaces_->GetInterface(&frame_input_handler_); } else { legacy_frame_input_handler_.reset(new LegacyIPCFrameInputHandler(this)); } + remote_interfaces_->GetInterface(&input_target_client_); } void RenderFrameHostImpl::InvalidateMojoConnection() {
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index c0080d5..ca028bde 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -55,6 +55,7 @@ #include "services/device/public/interfaces/wake_lock_context.mojom.h" #include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/interfaces/interface_provider.mojom.h" +#include "services/viz/public/interfaces/hit_test/input_target_client.mojom.h" #include "third_party/WebKit/common/feature_policy/feature_policy.h" #include "third_party/WebKit/public/platform/WebFocusType.h" #include "third_party/WebKit/public/platform/WebInsecureRequestPolicy.h" @@ -262,6 +263,10 @@ mojom::FrameInputHandler* GetFrameInputHandler(); + viz::mojom::InputTargetClient* GetInputTargetClient() { + return input_target_client_.get(); + } + // Creates a RenderFrame in the renderer process. bool CreateRenderFrame(int proxy_routing_id, int opener_routing_id, @@ -1438,6 +1443,7 @@ // have created one yet. base::Optional<base::UnguessableToken> overlay_routing_token_; + viz::mojom::InputTargetClientPtr input_target_client_; mojom::FrameInputHandlerPtr frame_input_handler_; std::unique_ptr<LegacyIPCFrameInputHandler> legacy_frame_input_handler_;
diff --git a/content/browser/frame_host/render_frame_host_impl_browsertest.cc b/content/browser/frame_host/render_frame_host_impl_browsertest.cc index 1894610..e7f4a16e 100644 --- a/content/browser/frame_host/render_frame_host_impl_browsertest.cc +++ b/content/browser/frame_host/render_frame_host_impl_browsertest.cc
@@ -11,6 +11,7 @@ #include "base/run_loop.h" #include "base/test/bind_test_util.h" #include "base/test/mock_callback.h" +#include "build/build_config.h" #include "content/browser/frame_host/navigation_handle_impl.h" #include "content/browser/interface_provider_filtering.h" #include "content/browser/web_contents/web_contents_impl.h" @@ -277,8 +278,14 @@ // Tests that a beforeunload dialog in an iframe doesn't stop the beforeunload // timer of a parent frame. +// TODO(avi): flaky on Linux TSAN: http://crbug.com/795326 +#if defined(OS_LINUX) && defined(THREAD_SANITIZER) +#define MAYBE_IframeBeforeUnloadParentHang DISABLED_IframeBeforeUnloadParentHang +#else +#define MAYBE_IframeBeforeUnloadParentHang IframeBeforeUnloadParentHang +#endif IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest, - IframeBeforeUnloadParentHang) { + MAYBE_IframeBeforeUnloadParentHang) { WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents()); TestJavaScriptDialogManager dialog_manager; wc->SetDelegate(&dialog_manager);
diff --git a/content/browser/gpu/gpu_data_manager_impl.cc b/content/browser/gpu/gpu_data_manager_impl.cc index 9236c58..8a471e3f 100644 --- a/content/browser/gpu/gpu_data_manager_impl.cc +++ b/content/browser/gpu/gpu_data_manager_impl.cc
@@ -147,13 +147,6 @@ private_->SetGLStrings(gl_vendor, gl_renderer, gl_version); } -void GpuDataManagerImpl::GetGLStrings(std::string* gl_vendor, - std::string* gl_renderer, - std::string* gl_version) { - base::AutoLock auto_lock(lock_); - private_->GetGLStrings(gl_vendor, gl_renderer, gl_version); -} - void GpuDataManagerImpl::DisableHardwareAcceleration() { base::AutoLock auto_lock(lock_); private_->DisableHardwareAcceleration();
diff --git a/content/browser/gpu/gpu_data_manager_impl.h b/content/browser/gpu/gpu_data_manager_impl.h index eddc5b0..2626ed24 100644 --- a/content/browser/gpu/gpu_data_manager_impl.h +++ b/content/browser/gpu/gpu_data_manager_impl.h
@@ -89,9 +89,6 @@ void SetGLStrings(const std::string& gl_vendor, const std::string& gl_renderer, const std::string& gl_version) override; - void GetGLStrings(std::string* gl_vendor, - std::string* gl_renderer, - std::string* gl_version) override; void DisableHardwareAcceleration() override; bool HardwareAccelerationEnabled() const override; void GetDisabledExtensions(std::string* disabled_extensions) const override;
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.cc b/content/browser/gpu/gpu_data_manager_impl_private.cc index 66ffedf..a0d0d3c 100644 --- a/content/browser/gpu/gpu_data_manager_impl_private.cc +++ b/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -394,32 +394,6 @@ return false; } - if (preliminary_blacklisted_features_initialized_) { - // We only need to block GPU process if more features are disallowed other - // than those in the preliminary gpu feature flags because the latter work - // through renderer commandline switches. WebGL and WebGL2 should not matter - // because their context creation can always be rejected on the GPU process - // side. - std::set<int> feature_diffs; - std::set_difference(blacklisted_features_.begin(), - blacklisted_features_.end(), - preliminary_blacklisted_features_.begin(), - preliminary_blacklisted_features_.end(), - std::inserter(feature_diffs, feature_diffs.begin())); - if (feature_diffs.size()) { - // TODO(zmo): Other features might also be OK to ignore here. - feature_diffs.erase(gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL); - feature_diffs.erase(gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL2); - feature_diffs.erase(gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS); - } - if (feature_diffs.size()) { - if (reason) { - *reason = "Features are disabled on full but not preliminary GPU info."; - } - return false; - } - } - if (blacklisted_features_.size() == gpu::NUMBER_OF_GPU_FEATURE_TYPES) { // On Linux, we use cached GL strings to make blacklist decsions at browser // startup time. We need to launch the GPU process to validate these @@ -546,17 +520,6 @@ gpu::CollectDriverInfoGL(&gpu_info); UpdateGpuInfo(gpu_info); - UpdatePreliminaryBlacklistedFeatures(); -} - -void GpuDataManagerImplPrivate::GetGLStrings(std::string* gl_vendor, - std::string* gl_renderer, - std::string* gl_version) { - DCHECK(gl_vendor && gl_renderer && gl_version); - - *gl_vendor = gpu_info_.gl_vendor; - *gl_renderer = gpu_info_.gl_renderer; - *gl_version = gpu_info_.gl_version; } void GpuDataManagerImplPrivate::Initialize() { @@ -994,7 +957,6 @@ GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(GpuDataManagerImpl* owner) : complete_gpu_info_already_requested_(false), - preliminary_blacklisted_features_initialized_(false), observer_list_(new GpuDataManagerObserverList), use_swiftshader_(false), card_blacklisted_(false), @@ -1047,7 +1009,6 @@ gpu_info_ = gpu_info; UpdateGpuInfo(gpu_info); - UpdatePreliminaryBlacklistedFeatures(); RunPostInitTasks(); } @@ -1076,11 +1037,6 @@ EnableSwiftShaderIfNecessary(); } -void GpuDataManagerImplPrivate::UpdatePreliminaryBlacklistedFeatures() { - preliminary_blacklisted_features_ = blacklisted_features_; - preliminary_blacklisted_features_initialized_ = true; -} - void GpuDataManagerImplPrivate::NotifyGpuInfoUpdate() { observer_list_->Notify(FROM_HERE, &GpuDataManagerObserver::OnGpuInfoUpdate); }
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.h b/content/browser/gpu/gpu_data_manager_impl_private.h index 19285a60..f40bc32 100644 --- a/content/browser/gpu/gpu_data_manager_impl_private.h +++ b/content/browser/gpu/gpu_data_manager_impl_private.h
@@ -61,9 +61,6 @@ void SetGLStrings(const std::string& gl_vendor, const std::string& gl_renderer, const std::string& gl_version); - void GetGLStrings(std::string* gl_vendor, - std::string* gl_renderer, - std::string* gl_version); void DisableHardwareAcceleration(); void SetGpuInfo(const gpu::GPUInfo& gpu_info); @@ -195,10 +192,6 @@ void UpdateBlacklistedFeatures(const std::set<int>& features); - // This should only be called once at initialization time, when preliminary - // gpu info is collected. - void UpdatePreliminaryBlacklistedFeatures(); - // Notify all observers whenever there is a GPU info update. void NotifyGpuInfoUpdate(); @@ -220,8 +213,6 @@ bool complete_gpu_info_already_requested_; std::set<int> blacklisted_features_; - std::set<int> preliminary_blacklisted_features_; - bool preliminary_blacklisted_features_initialized_; // Eventually |blacklisted_features_| should be folded in to this. gpu::GpuFeatureInfo gpu_feature_info_;
diff --git a/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc b/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc index ece02a81..0bc8a42 100644 --- a/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc +++ b/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc
@@ -519,142 +519,6 @@ GetDomain2ForTesting(), JustBeforeExpiration(manager.get()))); } -#if defined(OS_LINUX) -TEST_F(GpuDataManagerImplPrivateTest, SetGLStrings) { - const char* kGLVendorMesa = "Tungsten Graphics, Inc"; - const char* kGLRendererMesa = "Mesa DRI Intel(R) G41"; - const char* kGLVersionMesa801 = "2.1 Mesa 8.0.1-DEVEL"; - - ScopedGpuDataManagerImplPrivate manager; - EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); - EXPECT_TRUE(manager->GpuAccessAllowed(nullptr)); - - const gpu::GpuControlList::Entry kEntries[] = { - gpu::kGpuDataManagerTestingEntries - [gpu::kGpuDataManagerImplPrivateTest_SetGLStrings], - }; - const gpu::GpuControlListData kData(1, kEntries); - - gpu::GPUInfo gpu_info; - gpu_info.gpu.vendor_id = 0x8086; - gpu_info.gpu.device_id = 0x0042; - manager->InitializeForTesting(kData, gpu_info); - - // Not enough GPUInfo. - EXPECT_TRUE(manager->GpuAccessAllowed(nullptr)); - if (manager->ShouldUseSwiftShader()) { - EXPECT_EQ(static_cast<size_t>(gpu::NUMBER_OF_GPU_FEATURE_TYPES), - manager->GetBlacklistedFeatureCount()); - } else { - EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount()); - } - - // Now assume browser gets GL strings from local state. - // The entry applies, blacklist more features than from the preliminary step. - // However, GPU process is not blocked because this is all browser side and - // happens before renderer launching. - manager->SetGLStrings(kGLVendorMesa, kGLRendererMesa, kGLVersionMesa801); - EXPECT_TRUE(manager->GpuAccessAllowed(nullptr)); - if (manager->ShouldUseSwiftShader()) { - EXPECT_EQ(static_cast<size_t>(gpu::NUMBER_OF_GPU_FEATURE_TYPES), - manager->GetBlacklistedFeatureCount()); - } else { - EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount()); - } - EXPECT_TRUE( - manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL)); -} - -TEST_F(GpuDataManagerImplPrivateTest, SetGLStringsNoEffects) { - const char* kGLVendorMesa = "Tungsten Graphics, Inc"; - const char* kGLRendererMesa = "Mesa DRI Intel(R) G41"; - const char* kGLVersionMesa801 = "2.1 Mesa 8.0.1-DEVEL"; - const char* kGLVersionMesa802 = "2.1 Mesa 8.0.2-DEVEL"; - - ScopedGpuDataManagerImplPrivate manager; - EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); - EXPECT_TRUE(manager->GpuAccessAllowed(nullptr)); - - const gpu::GpuControlList::Entry kEntries[] = { - gpu::kGpuDataManagerTestingEntries - [gpu::kGpuDataManagerImplPrivateTest_SetGLStringsNoEffects], - }; - const gpu::GpuControlListData kData(1, kEntries); - - gpu::GPUInfo gpu_info; - gpu_info.gpu.vendor_id = 0x8086; - gpu_info.gpu.device_id = 0x0042; - gpu_info.gl_vendor = kGLVendorMesa; - gpu_info.gl_renderer = kGLRendererMesa; - gpu_info.gl_version = kGLVersionMesa801; - gpu_info.driver_vendor = "Mesa"; - gpu_info.driver_version = "8.0.1"; - manager->InitializeForTesting(kData, gpu_info); - - // Full GPUInfo, the entry applies. - EXPECT_TRUE(manager->GpuAccessAllowed(nullptr)); - if (manager->ShouldUseSwiftShader()) { - EXPECT_EQ(static_cast<size_t>(gpu::NUMBER_OF_GPU_FEATURE_TYPES), - manager->GetBlacklistedFeatureCount()); - } else { - EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount()); - } - EXPECT_TRUE( - manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL)); - - // Now assume browser gets GL strings from local state. - // SetGLStrings() has no effects because GPUInfo already got these strings. - // (Otherwise the entry should not apply.) - manager->SetGLStrings(kGLVendorMesa, kGLRendererMesa, kGLVersionMesa802); - EXPECT_TRUE(manager->GpuAccessAllowed(nullptr)); - if (manager->ShouldUseSwiftShader()) { - EXPECT_EQ(static_cast<size_t>(gpu::NUMBER_OF_GPU_FEATURE_TYPES), - manager->GetBlacklistedFeatureCount()); - } else { - EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount()); - } - EXPECT_TRUE( - manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL)); -} - -TEST_F(GpuDataManagerImplPrivateTest, SetGLStringsDefered) { - const char* kGLVendorMesa = "Tungsten Graphics, Inc"; - const char* kGLRendererMesa = "Mesa DRI Intel(R) G41"; - const char* kGLVersionMesa801 = "2.1 Mesa 8.0.1-DEVEL"; - - ScopedGpuDataManagerImplPrivate manager; - EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount()); - EXPECT_TRUE(manager->GpuAccessAllowed(nullptr)); - - const gpu::GpuControlList::Entry kEntries[] = { - gpu::kGpuDataManagerTestingEntries - [gpu::kGpuDataManagerImplPrivateTest_SetGLStringsDefered], - }; - const gpu::GpuControlListData kData(1, kEntries); - - // Check that it is allowed to call SetGLStrings before Initialize. - - // Assume browser gets GL strings from local state. - manager->SetGLStrings(kGLVendorMesa, kGLRendererMesa, kGLVersionMesa801); - - gpu::GPUInfo gpu_info; - gpu_info.gpu.vendor_id = 0x8086; - gpu_info.gpu.device_id = 0x0042; - manager->InitializeForTesting(kData, gpu_info); - - EXPECT_TRUE(manager->GpuAccessAllowed(nullptr)); - if (manager->ShouldUseSwiftShader()) { - EXPECT_EQ(static_cast<size_t>(gpu::NUMBER_OF_GPU_FEATURE_TYPES), - manager->GetBlacklistedFeatureCount()); - } else { - EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount()); - } - - EXPECT_TRUE( - manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL)); -} -#endif // OS_LINUX - TEST_F(GpuDataManagerImplPrivateTest, BlacklistAllFeatures) { ScopedGpuDataManagerImplPrivate manager; EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
diff --git a/content/browser/manifest/manifest_manager_host.cc b/content/browser/manifest/manifest_manager_host.cc index 31fa59f5..e51f748 100644 --- a/content/browser/manifest/manifest_manager_host.cc +++ b/content/browser/manifest/manifest_manager_host.cc
@@ -39,6 +39,11 @@ base::Unretained(this), request_id)); } +void ManifestManagerHost::RequestManifestDebugInfo( + blink::mojom::ManifestManager::RequestManifestDebugInfoCallback callback) { + GetManifestManager().RequestManifestDebugInfo(std::move(callback)); +} + blink::mojom::ManifestManager& ManifestManagerHost::GetManifestManager() { if (manifest_manager_frame_ != web_contents()->GetMainFrame()) OnConnectionError();
diff --git a/content/browser/manifest/manifest_manager_host.h b/content/browser/manifest/manifest_manager_host.h index bf70d70..0898480 100644 --- a/content/browser/manifest/manifest_manager_host.h +++ b/content/browser/manifest/manifest_manager_host.h
@@ -37,6 +37,9 @@ // have an empty manifest. void GetManifest(const GetManifestCallback& callback); + void RequestManifestDebugInfo( + blink::mojom::ManifestManager::RequestManifestDebugInfoCallback callback); + // WebContentsObserver void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
diff --git a/content/browser/renderer_host/DEPS b/content/browser/renderer_host/DEPS index 9f9d3a1..eb2fa51 100644 --- a/content/browser/renderer_host/DEPS +++ b/content/browser/renderer_host/DEPS
@@ -4,7 +4,9 @@ "+components/viz/host", "+components/viz/service", "+services/ui/public", + "+third_party/WebKit/public/platform/WebGestureCurve.h", "+third_party/zlib", + "+ui/events/gestures/blink/web_gesture_curve_impl.h", "+ui/latency", # The renderer_host files should only call upwards in the layering via the
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.h b/content/browser/renderer_host/browser_compositor_view_mac.h index 5634790..c4d926c6 100644 --- a/content/browser/renderer_host/browser_compositor_view_mac.h +++ b/content/browser/renderer_host/browser_compositor_view_mac.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "components/viz/common/frame_sinks/begin_frame_source.h" #include "components/viz/common/surfaces/local_surface_id.h" +#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" #include "content/browser/renderer_host/delegated_frame_host.h" #include "ui/compositor/compositor.h" #include "ui/compositor/compositor_observer.h" @@ -26,7 +27,6 @@ public: virtual SkColor BrowserCompositorMacGetGutterColor(SkColor color) const = 0; virtual void BrowserCompositorMacOnBeginFrame() = 0; - virtual viz::LocalSurfaceId GetLocalSurfaceId() const = 0; virtual void OnFrameTokenChanged(uint32_t frame_token) = 0; }; @@ -107,7 +107,7 @@ viz::LocalSurfaceId GetLocalSurfaceId() const override; std::unique_ptr<CompositorResizeLock> DelegatedFrameHostCreateResizeLock() override; - void OnBeginFrame() override; + void OnBeginFrame(base::TimeTicks frame_time) override; bool IsAutoResizeEnabled() const override; void OnFrameTokenChanged(uint32_t frame_token) override; @@ -178,6 +178,8 @@ const bool enable_viz_ = false; viz::mojom::CompositorFrameSinkClient* renderer_compositor_frame_sink_ = nullptr; + viz::LocalSurfaceId compositor_surface_id_; + viz::ParentLocalSurfaceIdAllocator parent_local_surface_id_allocator_; base::WeakPtrFactory<BrowserCompositorMac> weak_factory_; };
diff --git a/content/browser/renderer_host/browser_compositor_view_mac.mm b/content/browser/renderer_host/browser_compositor_view_mac.mm index 6cb6a6a50..c5917ce6 100644 --- a/content/browser/renderer_host/browser_compositor_view_mac.mm +++ b/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -12,6 +12,7 @@ #include "base/containers/circular_deque.h" #include "base/lazy_instance.h" #include "base/trace_event/trace_event.h" +#include "components/viz/common/features.h" #include "components/viz/common/switches.h" #include "content/browser/compositor/image_transport_factory.h" #include "content/browser/renderer_host/compositor_resize_lock.h" @@ -109,7 +110,7 @@ content::GetContextFactory(), content::GetContextFactoryPrivate(), ui::WindowResizeHelperMac::Get()->task_runner(), - false /* enable_surface_synchronization */, + features::IsSurfaceSynchronizationEnabled(), false /* enable_pixel_canvas */) { compositor_.SetAcceleratedWidget( accelerated_widget_mac_->accelerated_widget()); @@ -188,9 +189,8 @@ g_browser_compositor_count += 1; root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR)); - // TODO(fsamuel): Plumb surface synchronization settings. delegated_frame_host_.reset(new DelegatedFrameHost( - frame_sink_id, this, false /* enable_surface_synchronization */, + frame_sink_id, this, features::IsSurfaceSynchronizationEnabled(), enable_viz_)); SetRenderWidgetHostIsHidden(render_widget_host_is_hidden); @@ -342,14 +342,24 @@ // In non-viz, the ui::Compositor is resized in sync with frames coming from // the renderer. In viz, the ui::Compositor can only resize in sync with the // NSView. - if (enable_viz_ && recyclable_compositor_) { - gfx::Size dip_size; - float scale_factor = 1.f; - GetViewProperties(&dip_size, &scale_factor, nullptr); - gfx::Size pixel_size = gfx::ConvertSizeToPixel(scale_factor, dip_size); - recyclable_compositor_->compositor()->SetScaleAndSize(scale_factor, - pixel_size); - } + if (!enable_viz_ || !recyclable_compositor_) + return; + + gfx::Size dip_size; + float scale_factor = 1.f; + GetViewProperties(&dip_size, &scale_factor, nullptr); + gfx::Size pixel_size = gfx::ConvertSizeToPixel(scale_factor, dip_size); + + gfx::Size old_pixel_size = recyclable_compositor_->compositor()->size(); + float old_scale_factor = + recyclable_compositor_->compositor()->device_scale_factor(); + + if (pixel_size == old_pixel_size && scale_factor == old_scale_factor) + return; + + compositor_surface_id_ = parent_local_surface_id_allocator_.GenerateId(); + recyclable_compositor_->compositor()->SetScaleAndSize( + scale_factor, pixel_size, compositor_surface_id_); } bool BrowserCompositorMac::HasFrameOfSize(const gfx::Size& desired_size) { @@ -499,7 +509,7 @@ } viz::LocalSurfaceId BrowserCompositorMac::GetLocalSurfaceId() const { - return client_->GetLocalSurfaceId(); + return compositor_surface_id_; } std::unique_ptr<CompositorResizeLock> @@ -508,7 +518,7 @@ return nullptr; } -void BrowserCompositorMac::OnBeginFrame() { +void BrowserCompositorMac::OnBeginFrame(base::TimeTicks frame_time) { client_->BrowserCompositorMacOnBeginFrame(); }
diff --git a/content/browser/renderer_host/clipboard_host_impl.cc b/content/browser/renderer_host/clipboard_host_impl.cc index 8b6a0ca..3b48de9 100644 --- a/content/browser/renderer_host/clipboard_host_impl.cc +++ b/content/browser/renderer_host/clipboard_host_impl.cc
@@ -4,6 +4,7 @@ #include "content/browser/renderer_host/clipboard_host_impl.h" +#include <limits> #include <utility> #include "base/bind.h" @@ -68,20 +69,16 @@ clipboard_writer_->Reset(); } -void ClipboardHostImpl::GetSequenceNumber(blink::mojom::ClipboardBuffer buffer, +void ClipboardHostImpl::GetSequenceNumber(ui::ClipboardType clipboard_type, GetSequenceNumberCallback callback) { - ui::ClipboardType clipboard_type; - ConvertBufferType(buffer, &clipboard_type); DCHECK_CURRENTLY_ON(BrowserThread::UI); std::move(callback).Run(clipboard_->GetSequenceNumber(clipboard_type)); } void ClipboardHostImpl::ReadAvailableTypes( - blink::mojom::ClipboardBuffer buffer, + ui::ClipboardType clipboard_type, ReadAvailableTypesCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - ui::ClipboardType clipboard_type; - ConvertBufferType(buffer, &clipboard_type); std::vector<base::string16> types; bool contains_filenames; clipboard_->ReadAvailableTypes(clipboard_type, &types, &contains_filenames); @@ -89,11 +86,9 @@ } void ClipboardHostImpl::IsFormatAvailable(blink::mojom::ClipboardFormat format, - blink::mojom::ClipboardBuffer buffer, + ui::ClipboardType clipboard_type, IsFormatAvailableCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - ui::ClipboardType clipboard_type; - ConvertBufferType(buffer, &clipboard_type); bool result = false; switch (format) { case blink::mojom::ClipboardFormat::kPlaintext: @@ -122,11 +117,9 @@ std::move(callback).Run(result); } -void ClipboardHostImpl::ReadText(blink::mojom::ClipboardBuffer buffer, +void ClipboardHostImpl::ReadText(ui::ClipboardType clipboard_type, ReadTextCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - ui::ClipboardType clipboard_type; - ConvertBufferType(buffer, &clipboard_type); base::string16 result; if (clipboard_->IsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(), @@ -141,11 +134,9 @@ std::move(callback).Run(result); } -void ClipboardHostImpl::ReadHtml(blink::mojom::ClipboardBuffer buffer, +void ClipboardHostImpl::ReadHtml(ui::ClipboardType clipboard_type, ReadHtmlCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - ui::ClipboardType clipboard_type; - ConvertBufferType(buffer, &clipboard_type); base::string16 markup; std::string src_url_str; @@ -157,22 +148,18 @@ fragment_end); } -void ClipboardHostImpl::ReadRtf(blink::mojom::ClipboardBuffer buffer, +void ClipboardHostImpl::ReadRtf(ui::ClipboardType clipboard_type, ReadRtfCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - ui::ClipboardType clipboard_type; - ConvertBufferType(buffer, &clipboard_type); std::string result; clipboard_->ReadRTF(clipboard_type, &result); std::move(callback).Run(result); } -void ClipboardHostImpl::ReadImage(blink::mojom::ClipboardBuffer buffer, +void ClipboardHostImpl::ReadImage(ui::ClipboardType clipboard_type, ReadImageCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - ui::ClipboardType clipboard_type; - ConvertBufferType(buffer, &clipboard_type); SkBitmap bitmap = clipboard_->ReadImage(clipboard_type); @@ -233,39 +220,36 @@ std::move(callback).Run(std::string(), std::string(), -1); } -void ClipboardHostImpl::ReadCustomData(blink::mojom::ClipboardBuffer buffer, +void ClipboardHostImpl::ReadCustomData(ui::ClipboardType clipboard_type, const base::string16& type, ReadCustomDataCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - ui::ClipboardType clipboard_type; - ConvertBufferType(buffer, &clipboard_type); base::string16 result; clipboard_->ReadCustomData(clipboard_type, type, &result); std::move(callback).Run(result); } -void ClipboardHostImpl::WriteText(blink::mojom::ClipboardBuffer, +void ClipboardHostImpl::WriteText(ui::ClipboardType, const base::string16& text) { DCHECK_CURRENTLY_ON(BrowserThread::UI); clipboard_writer_->WriteText(text); } -void ClipboardHostImpl::WriteHtml(blink::mojom::ClipboardBuffer, +void ClipboardHostImpl::WriteHtml(ui::ClipboardType, const base::string16& markup, const GURL& url) { DCHECK_CURRENTLY_ON(BrowserThread::UI); clipboard_writer_->WriteHTML(markup, url.spec()); } -void ClipboardHostImpl::WriteSmartPasteMarker( - blink::mojom::ClipboardBuffer buffer) { +void ClipboardHostImpl::WriteSmartPasteMarker(ui::ClipboardType) { DCHECK_CURRENTLY_ON(BrowserThread::UI); clipboard_writer_->WriteWebSmartPaste(); } void ClipboardHostImpl::WriteCustomData( - blink::mojom::ClipboardBuffer, + ui::ClipboardType, const std::unordered_map<base::string16, base::string16>& data) { DCHECK_CURRENTLY_ON(BrowserThread::UI); base::Pickle pickle; @@ -274,7 +258,7 @@ pickle, ui::Clipboard::GetWebCustomDataFormatType()); } -void ClipboardHostImpl::WriteBookmark(blink::mojom::ClipboardBuffer, +void ClipboardHostImpl::WriteBookmark(ui::ClipboardType, const std::string& url, const base::string16& title) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -282,7 +266,7 @@ } void ClipboardHostImpl::WriteImage( - blink::mojom::ClipboardBuffer, + ui::ClipboardType, const gfx::Size& size, mojo::ScopedSharedBufferHandle shared_buffer_handle) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -310,7 +294,7 @@ clipboard_writer_->WriteImage(bitmap); } -void ClipboardHostImpl::CommitWrite(blink::mojom::ClipboardBuffer) { +void ClipboardHostImpl::CommitWrite(ui::ClipboardType) { DCHECK_CURRENTLY_ON(BrowserThread::UI); clipboard_writer_.reset( new ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE)); @@ -322,22 +306,4 @@ } #endif -void ClipboardHostImpl::ConvertBufferType(blink::mojom::ClipboardBuffer buffer, - ui::ClipboardType* result) { - *result = ui::CLIPBOARD_TYPE_COPY_PASTE; - switch (buffer) { - case blink::mojom::ClipboardBuffer::kStandard: - break; - case blink::mojom::ClipboardBuffer::kSelection: -#if defined(USE_X11) - *result = ui::CLIPBOARD_TYPE_SELECTION; - break; -#else - // Chrome OS and non-X11 unix builds do not support - // the X selection clipboad. - // TODO: remove the need for this case, see http://crbug.com/361753 - mojo::ReportBadMessage("Cannot use kSelection on non X11 platforms."); -#endif - } -} } // namespace content
diff --git a/content/browser/renderer_host/clipboard_host_impl.h b/content/browser/renderer_host/clipboard_host_impl.h index 70aa3561..834a25e 100644 --- a/content/browser/renderer_host/clipboard_host_impl.h +++ b/content/browser/renderer_host/clipboard_host_impl.h
@@ -56,44 +56,42 @@ ReadImageCallback callback); // content::mojom::ClipboardHost - void GetSequenceNumber(blink::mojom::ClipboardBuffer buffer, + void GetSequenceNumber(ui::ClipboardType clipboard_type, GetSequenceNumberCallback callback) override; void IsFormatAvailable(blink::mojom::ClipboardFormat format, - blink::mojom::ClipboardBuffer buffer, + ui::ClipboardType clipboard_type, IsFormatAvailableCallback callback) override; - void ReadAvailableTypes(blink::mojom::ClipboardBuffer buffer, + void ReadAvailableTypes(ui::ClipboardType clipboard_type, ReadAvailableTypesCallback callback) override; - void ReadText(blink::mojom::ClipboardBuffer buffer, + void ReadText(ui::ClipboardType clipboard_type, ReadTextCallback callback) override; - void ReadHtml(blink::mojom::ClipboardBuffer buffer, + void ReadHtml(ui::ClipboardType clipboard_type, ReadHtmlCallback callback) override; - void ReadRtf(blink::mojom::ClipboardBuffer buffer, + void ReadRtf(ui::ClipboardType clipboard_type, ReadRtfCallback callback) override; - void ReadImage(blink::mojom::ClipboardBuffer buffer, + void ReadImage(ui::ClipboardType clipboard_type, ReadImageCallback callback) override; - void ReadCustomData(blink::mojom::ClipboardBuffer buffer, + void ReadCustomData(ui::ClipboardType clipboard_type, const base::string16& type, ReadCustomDataCallback callback) override; - void WriteText(blink::mojom::ClipboardBuffer buffer, + void WriteText(ui::ClipboardType clipboard_type, const base::string16& text) override; - void WriteHtml(blink::mojom::ClipboardBuffer buffer, + void WriteHtml(ui::ClipboardType clipboard_type, const base::string16& markup, const GURL& url) override; - void WriteSmartPasteMarker(blink::mojom::ClipboardBuffer buffer) override; + void WriteSmartPasteMarker(ui::ClipboardType clipboard_type) override; void WriteCustomData( - blink::mojom::ClipboardBuffer buffer, + ui::ClipboardType clipboard_type, const std::unordered_map<base::string16, base::string16>& data) override; - void WriteBookmark(blink::mojom::ClipboardBuffer buffer, + void WriteBookmark(ui::ClipboardType clipboard_type, const std::string& url, const base::string16& title) override; - void WriteImage(blink::mojom::ClipboardBuffer buffer, + void WriteImage(ui::ClipboardType clipboard_type, const gfx::Size& size_in_pixels, mojo::ScopedSharedBufferHandle shared_buffer_handle) override; - void CommitWrite(blink::mojom::ClipboardBuffer buffer) override; + void CommitWrite(ui::ClipboardType clipboard_type) override; void WriteStringToFindPboard(const base::string16& text) override; - void ConvertBufferType(blink::mojom::ClipboardBuffer, ui::ClipboardType*); - ui::Clipboard* clipboard_; // Not owned scoped_refptr<ChromeBlobStorageContext> blob_storage_context_; std::unique_ptr<ui::ScopedClipboardWriter> clipboard_writer_;
diff --git a/content/browser/renderer_host/clipboard_host_impl_unittest.cc b/content/browser/renderer_host/clipboard_host_impl_unittest.cc index e0e5d5e..618b97cf 100644 --- a/content/browser/renderer_host/clipboard_host_impl_unittest.cc +++ b/content/browser/renderer_host/clipboard_host_impl_unittest.cc
@@ -35,12 +35,12 @@ mojo::ScopedSharedBufferHandle shared_memory, size_t shared_memory_size) { host_->WriteImage( - blink::mojom::ClipboardBuffer::kStandard, size, + ui::CLIPBOARD_TYPE_COPY_PASTE, size, shared_memory->Clone(mojo::SharedBufferHandle::AccessMode::READ_ONLY)); } void CallCommitWrite() { - host_->CommitWrite(blink::mojom::ClipboardBuffer::kStandard); + host_->CommitWrite(ui::CLIPBOARD_TYPE_COPY_PASTE); base::RunLoop().RunUntilIdle(); }
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc index 3931676..a1e7683 100644 --- a/content/browser/renderer_host/delegated_frame_host.cc +++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -613,7 +613,7 @@ void DelegatedFrameHost::OnBeginFrame(const viz::BeginFrameArgs& args) { if (renderer_compositor_frame_sink_) renderer_compositor_frame_sink_->OnBeginFrame(args); - client_->OnBeginFrame(); + client_->OnBeginFrame(args.frame_time); } void DelegatedFrameHost::EvictDelegatedFrame() {
diff --git a/content/browser/renderer_host/delegated_frame_host.h b/content/browser/renderer_host/delegated_frame_host.h index c7a0c51..963f76e 100644 --- a/content/browser/renderer_host/delegated_frame_host.h +++ b/content/browser/renderer_host/delegated_frame_host.h
@@ -71,7 +71,7 @@ DelegatedFrameHostCreateResizeLock() = 0; virtual viz::LocalSurfaceId GetLocalSurfaceId() const = 0; - virtual void OnBeginFrame() = 0; + virtual void OnBeginFrame(base::TimeTicks frame_time) = 0; virtual bool IsAutoResizeEnabled() const = 0; virtual void OnFrameTokenChanged(uint32_t frame_token) = 0; };
diff --git a/content/browser/renderer_host/delegated_frame_host_client_aura.cc b/content/browser/renderer_host/delegated_frame_host_client_aura.cc index 61cd6f8..4c1905e 100644 --- a/content/browser/renderer_host/delegated_frame_host_client_aura.cc +++ b/content/browser/renderer_host/delegated_frame_host_client_aura.cc
@@ -77,8 +77,8 @@ return render_widget_host_view_->GetLocalSurfaceId(); } -void DelegatedFrameHostClientAura::OnBeginFrame() { - render_widget_host_view_->OnBeginFrame(); +void DelegatedFrameHostClientAura::OnBeginFrame(base::TimeTicks frame_time) { + render_widget_host_view_->OnBeginFrame(frame_time); } bool DelegatedFrameHostClientAura::IsAutoResizeEnabled() const {
diff --git a/content/browser/renderer_host/delegated_frame_host_client_aura.h b/content/browser/renderer_host/delegated_frame_host_client_aura.h index 37a79d17..6f5590be 100644 --- a/content/browser/renderer_host/delegated_frame_host_client_aura.h +++ b/content/browser/renderer_host/delegated_frame_host_client_aura.h
@@ -37,7 +37,7 @@ std::unique_ptr<CompositorResizeLock> DelegatedFrameHostCreateResizeLock() override; viz::LocalSurfaceId GetLocalSurfaceId() const override; - void OnBeginFrame() override; + void OnBeginFrame(base::TimeTicks frame_time) override; bool IsAutoResizeEnabled() const override; void OnFrameTokenChanged(uint32_t frame_token) override;
diff --git a/content/browser/renderer_host/input/fling_controller.cc b/content/browser/renderer_host/input/fling_controller.cc index f3e9c07..f716da42 100644 --- a/content/browser/renderer_host/input/fling_controller.cc +++ b/content/browser/renderer_host/input/fling_controller.cc
@@ -5,8 +5,22 @@ #include "content/browser/renderer_host/input/fling_controller.h" #include "content/browser/renderer_host/input/gesture_event_queue.h" +#include "content/public/common/content_features.h" +#include "ui/events/base_event_utils.h" +#include "ui/events/blink/fling_booster.h" +#include "ui/events/gestures/blink/web_gesture_curve_impl.h" using blink::WebInputEvent; +using blink::WebGestureEvent; + +namespace { +// Maximum time between a fling event's timestamp and the first |Progress| call +// for the fling curve to use the fling timestamp as the initial animation time. +// Two frames allows a minor delay between event creation and the first +// progress. +constexpr base::TimeDelta kMaxMicrosecondsFromFlingTimestampToFirstProgress = + base::TimeDelta::FromMicroseconds(33333); +} // namespace namespace content { @@ -15,16 +29,24 @@ FlingController::FlingController( GestureEventQueue* gesture_event_queue, TouchpadTapSuppressionControllerClient* touchpad_client, + FlingControllerClient* fling_client, const Config& config) : gesture_event_queue_(gesture_event_queue), + client_(fling_client), touchpad_tap_suppression_controller_( touchpad_client, config.touchpad_tap_suppression_config), touchscreen_tap_suppression_controller_( gesture_event_queue, - config.touchscreen_tap_suppression_config) { + config.touchscreen_tap_suppression_config), + fling_in_progress_(false), + send_wheel_events_nonblocking_( + base::FeatureList::IsEnabled( + features::kTouchpadAndWheelScrollLatching) && + base::FeatureList::IsEnabled(features::kAsyncWheelEvents)) { DCHECK(gesture_event_queue); DCHECK(touchpad_client); + DCHECK(fling_client); } FlingController::~FlingController() {} @@ -33,6 +55,12 @@ const GestureEventWithLatencyInfo& gesture_event) const { if (gesture_event.event.GetType() != WebInputEvent::kGestureFlingCancel) return true; + + if (fling_in_progress_) + return !fling_booster_->fling_cancellation_is_deferred(); + + // Touchpad fling with wheel scroll latching disabled, touchscreen, and + // auto-scroll flings are still handled by renderer. return !gesture_event_queue_->ShouldDiscardFlingCancelEvent(gesture_event); } @@ -41,11 +69,12 @@ switch (gesture_event.event.GetType()) { case WebInputEvent::kGestureFlingCancel: if (gesture_event.event.source_device == - blink::kWebGestureDeviceTouchscreen) + blink::kWebGestureDeviceTouchscreen) { touchscreen_tap_suppression_controller_.GestureFlingCancel(); - else if (gesture_event.event.source_device == - blink::kWebGestureDeviceTouchpad) + } else if (gesture_event.event.source_device == + blink::kWebGestureDeviceTouchpad) { touchpad_tap_suppression_controller_.GestureFlingCancel(); + } return true; case WebInputEvent::kGestureTapDown: case WebInputEvent::kGestureShowPress: @@ -67,19 +96,235 @@ } } -bool FlingController::FilterGestureEvent( +bool FlingController::FilterGestureEventForFlingBoosting( const GestureEventWithLatencyInfo& gesture_event) { - return (!ShouldForwardForGFCFiltering(gesture_event) || - !ShouldForwardForTapSuppression(gesture_event)); + if (!fling_booster_) + return false; + + bool cancel_current_fling; + bool should_filter_event = fling_booster_->FilterGestureEventForFlingBoosting( + gesture_event.event, &cancel_current_fling); + if (cancel_current_fling) { + CancelCurrentFling(); + } + + if (should_filter_event && + gesture_event.event.GetType() == WebInputEvent::kGestureFlingStart) { + UpdateCurrentFlingState(gesture_event.event, + fling_booster_->current_fling_velocity()); + } + + return should_filter_event; } -void FlingController::GestureFlingCancelAck( - blink::WebGestureDevice source_device, - bool processed) { - if (source_device == blink::kWebGestureDeviceTouchscreen) - touchscreen_tap_suppression_controller_.GestureFlingCancelAck(processed); - else if (source_device == blink::kWebGestureDeviceTouchpad) - touchpad_tap_suppression_controller_.GestureFlingCancelAck(processed); +bool FlingController::FilterGestureEvent( + const GestureEventWithLatencyInfo& gesture_event) { + return !ShouldForwardForGFCFiltering(gesture_event) || + !ShouldForwardForTapSuppression(gesture_event) || + FilterGestureEventForFlingBoosting(gesture_event); +} + +void FlingController::OnGestureEventAck( + const GestureEventWithLatencyInfo& acked_event, + InputEventAckState ack_result) { + bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result); + switch (acked_event.event.GetType()) { + case WebInputEvent::kGestureFlingCancel: { + blink::WebGestureDevice source_device = acked_event.event.source_device; + if (source_device == blink::kWebGestureDeviceTouchscreen) { + touchscreen_tap_suppression_controller_.GestureFlingCancelAck( + processed); + } else if (source_device == blink::kWebGestureDeviceTouchpad) { + touchpad_tap_suppression_controller_.GestureFlingCancelAck(processed); + } + break; + } + case WebInputEvent::kGestureScrollUpdate: + if (acked_event.event.data.scroll_update.inertial_phase == + WebGestureEvent::kMomentumPhase && + fling_curve_ && !processed) { + CancelCurrentFling(); + } + default: + break; + } +} + +void FlingController::ProcessGestureFlingStart( + const GestureEventWithLatencyInfo& gesture_event) { + const float vx = gesture_event.event.data.fling_start.velocity_x; + const float vy = gesture_event.event.data.fling_start.velocity_y; + if (!UpdateCurrentFlingState(gesture_event.event, gfx::Vector2dF(vx, vy))) + return; + has_fling_animation_started_ = false; + fling_in_progress_ = true; + fling_booster_ = std::make_unique<ui::FlingBooster>( + current_fling_parameters_.velocity, + current_fling_parameters_.source_device, + current_fling_parameters_.modifiers); + ScheduleFlingProgress(); +} + +void FlingController::ScheduleFlingProgress() { + client_->SetNeedsBeginFrameForFlingProgress(); +} + +void FlingController::ProcessGestureFlingCancel( + const GestureEventWithLatencyInfo& gesture_event) { + fling_in_progress_ = false; + if (fling_curve_) { + CancelCurrentFling(); + + // FlingCancelEvent handled without being sent to the renderer. + touchpad_tap_suppression_controller_.GestureFlingCancelAck(true); + return; + } + + // FlingCancelEvent ignored without being sent to the renderer. + touchpad_tap_suppression_controller_.GestureFlingCancelAck(false); +} + +void FlingController::ProgressFling(base::TimeTicks current_time) { + if (!fling_curve_) + return; + + DCHECK(fling_booster_); + fling_booster_->set_last_fling_animation_time( + (current_time - base::TimeTicks()).InSecondsF()); + if (fling_booster_->MustCancelDeferredFling()) { + CancelCurrentFling(); + return; + } + if (!has_fling_animation_started_) { + // Guard against invalid, future or sufficiently stale start times, as there + // are no guarantees fling event and progress timestamps are compatible. + if (current_fling_parameters_.start_time.is_null() || + current_time <= current_fling_parameters_.start_time || + current_time >= current_fling_parameters_.start_time + + kMaxMicrosecondsFromFlingTimestampToFirstProgress) { + current_fling_parameters_.start_time = current_time; + ScheduleFlingProgress(); + return; + } + } + + gfx::Vector2dF current_velocity; + gfx::Vector2dF delta_to_scroll; + bool fling_is_active = fling_curve_->Advance( + (current_time - current_fling_parameters_.start_time).InSecondsF(), + current_velocity, delta_to_scroll); + if (fling_is_active) { + if (delta_to_scroll != gfx::Vector2d()) { + blink::WebMouseWheelEvent::Phase phase = + has_fling_animation_started_ + ? blink::WebMouseWheelEvent::kPhaseChanged + : blink::WebMouseWheelEvent::kPhaseBegan; + GenerateAndSendWheelEvents(delta_to_scroll, phase); + has_fling_animation_started_ = true; + ScheduleFlingProgress(); + } + } else { // !is_fling_active + CancelCurrentFling(); + } +} + +void FlingController::GenerateAndSendWheelEvents( + gfx::Vector2dF delta, + blink::WebMouseWheelEvent::Phase phase) { + MouseWheelEventWithLatencyInfo synthetic_wheel( + WebInputEvent::kMouseWheel, current_fling_parameters_.modifiers, + ui::EventTimeStampToSeconds(base::TimeTicks::Now()), + ui::LatencyInfo(ui::SourceEventType::WHEEL)); + synthetic_wheel.event.delta_x = delta.x(); + synthetic_wheel.event.delta_y = delta.y(); + synthetic_wheel.event.has_precise_scrolling_deltas = true; + synthetic_wheel.event.momentum_phase = phase; + synthetic_wheel.event.has_synthetic_phase = true; + synthetic_wheel.event.SetPositionInWidget( + current_fling_parameters_.point.x(), current_fling_parameters_.point.y()); + synthetic_wheel.event.SetPositionInScreen( + current_fling_parameters_.global_point.x(), + current_fling_parameters_.global_point.y()); + // Send wheel end events nonblocking since they have zero delta and are not + // sent to JS. + if (phase == blink::WebMouseWheelEvent::kPhaseEnded) { + synthetic_wheel.event.dispatch_type = WebInputEvent::kEventNonBlocking; + } else { + synthetic_wheel.event.dispatch_type = send_wheel_events_nonblocking_ + ? WebInputEvent::kEventNonBlocking + : WebInputEvent::kBlocking; + } + + client_->SendGeneratedWheelEvent(synthetic_wheel); +} + +void FlingController::CancelCurrentFling() { + fling_curve_.reset(); + has_fling_animation_started_ = false; + fling_in_progress_ = false; + GenerateAndSendWheelEvents(gfx::Vector2d(), + blink::WebMouseWheelEvent::kPhaseEnded); + current_fling_parameters_ = ActiveFlingParameters(); + + if (fling_booster_) { + if (fling_booster_->fling_cancellation_is_deferred()) { + WebGestureEvent last_fling_boost_event = + fling_booster_->last_boost_event(); + fling_booster_.reset(); + if (last_fling_boost_event.GetType() == + WebInputEvent::kGestureScrollBegin || + last_fling_boost_event.GetType() == + WebInputEvent::kGestureScrollUpdate) { + // Synthesize a GestureScrollBegin, as the original event was + // suppressed. + WebGestureEvent scroll_begin_event = last_fling_boost_event; + scroll_begin_event.SetType(WebInputEvent::kGestureScrollBegin); + scroll_begin_event.SetTimeStampSeconds( + ui::EventTimeStampToSeconds(base::TimeTicks::Now())); + bool is_update = last_fling_boost_event.GetType() == + WebInputEvent::kGestureScrollUpdate; + float delta_x_hint = + is_update ? last_fling_boost_event.data.scroll_update.delta_x + : last_fling_boost_event.data.scroll_begin.delta_x_hint; + float delta_y_hint = + is_update ? last_fling_boost_event.data.scroll_update.delta_y + : last_fling_boost_event.data.scroll_begin.delta_y_hint; + scroll_begin_event.data.scroll_begin.delta_x_hint = delta_x_hint; + scroll_begin_event.data.scroll_begin.delta_y_hint = delta_y_hint; + gesture_event_queue_->QueueEvent(GestureEventWithLatencyInfo( + scroll_begin_event, ui::LatencyInfo(ui::SourceEventType::WHEEL))); + } + } else { + fling_booster_.reset(); + } + } +} + +bool FlingController::UpdateCurrentFlingState( + const WebGestureEvent& fling_start_event, + const gfx::Vector2dF& velocity) { + DCHECK_EQ(WebInputEvent::kGestureFlingStart, fling_start_event.GetType()); + if (velocity.IsZero()) { + CancelCurrentFling(); + return false; + } + + current_fling_parameters_.velocity = velocity; + current_fling_parameters_.point = + gfx::Vector2d(fling_start_event.x, fling_start_event.y); + current_fling_parameters_.global_point = + gfx::Vector2d(fling_start_event.global_x, fling_start_event.global_y); + current_fling_parameters_.modifiers = fling_start_event.GetModifiers(); + current_fling_parameters_.source_device = fling_start_event.source_device; + current_fling_parameters_.start_time = + base::TimeTicks() + + base::TimeDelta::FromSecondsD(fling_start_event.TimeStampSeconds()); + fling_curve_ = std::unique_ptr<blink::WebGestureCurve>( + ui::WebGestureCurveImpl::CreateFromDefaultPlatformCurve( + current_fling_parameters_.source_device, + current_fling_parameters_.velocity, + gfx::Vector2dF() /*initial_offset*/, false /*on_main_thread*/)); + return true; } TouchpadTapSuppressionController*
diff --git a/content/browser/renderer_host/input/fling_controller.h b/content/browser/renderer_host/input/fling_controller.h index 8dac169..85fc55c 100644 --- a/content/browser/renderer_host/input/fling_controller.h +++ b/content/browser/renderer_host/input/fling_controller.h
@@ -2,17 +2,37 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FLING_CONTROLLER_H_ -#define FLING_CONTROLLER_H_ +#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_FLING_CONTROLLER_H_ +#define CONTENT_BROWSER_RENDERER_HOST_INPUT_FLING_CONTROLLER_H_ #include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h" #include "content/browser/renderer_host/input/touchscreen_tap_suppression_controller.h" +#include "content/public/common/input_event_ack_state.h" + +namespace blink { +class WebGestureCurve; +} + +namespace ui { +class FlingBooster; +} namespace content { class GestureEventQueue; -class FlingController { +// Interface with which the FlingController can forward generated wheel events. +class CONTENT_EXPORT FlingControllerClient { + public: + virtual ~FlingControllerClient() {} + + virtual void SendGeneratedWheelEvent( + const MouseWheelEventWithLatencyInfo& wheel_event) = 0; + + virtual void SetNeedsBeginFrameForFlingProgress() = 0; +}; + +class CONTENT_EXPORT FlingController { public: struct CONTENT_EXPORT Config { Config(); @@ -24,12 +44,47 @@ TapSuppressionController::Config touchscreen_tap_suppression_config; }; + struct ActiveFlingParameters { + gfx::Vector2dF velocity; + gfx::Vector2d point; + gfx::Vector2d global_point; + int modifiers; + blink::WebGestureDevice source_device; + base::TimeTicks start_time; + + ActiveFlingParameters() : modifiers(0) {} + }; + FlingController(GestureEventQueue* gesture_event_queue, TouchpadTapSuppressionControllerClient* touchpad_client, + FlingControllerClient* fling_client, const Config& config); ~FlingController(); + // Used to progress an active fling on every begin frame. + void ProgressFling(base::TimeTicks current_time); + + bool FilterGestureEvent(const GestureEventWithLatencyInfo& gesture_event); + + void OnGestureEventAck(const GestureEventWithLatencyInfo& acked_event, + InputEventAckState ack_result); + + void ProcessGestureFlingStart( + const GestureEventWithLatencyInfo& gesture_event); + + void ProcessGestureFlingCancel( + const GestureEventWithLatencyInfo& gesture_event); + + bool fling_in_progress() const { return fling_in_progress_; } + + // Returns the |TouchpadTapSuppressionController| instance. + TouchpadTapSuppressionController* GetTouchpadTapSuppressionController(); + + protected: + std::unique_ptr<ui::FlingBooster> fling_booster_; + + private: // Sub-filter for removing unnecessary GestureFlingCancels. bool ShouldForwardForGFCFiltering( const GestureEventWithLatencyInfo& gesture_event) const; @@ -38,17 +93,26 @@ bool ShouldForwardForTapSuppression( const GestureEventWithLatencyInfo& gesture_event); - bool FilterGestureEvent(const GestureEventWithLatencyInfo& gesture_event); + // Sub-filter for suppressing gesture events to boost an active fling whenever + // possible. + bool FilterGestureEventForFlingBoosting( + const GestureEventWithLatencyInfo& gesture_event); - void GestureFlingCancelAck(blink::WebGestureDevice source_device, - bool processed); + void ScheduleFlingProgress(); - // Returns the |TouchpadTapSuppressionController| instance. - TouchpadTapSuppressionController* GetTouchpadTapSuppressionController(); + // Used to generate synthetic wheel events from touchpad fling and send them. + void GenerateAndSendWheelEvents(gfx::Vector2dF delta, + blink::WebMouseWheelEvent::Phase phase); - private: + void CancelCurrentFling(); + + bool UpdateCurrentFlingState(const blink::WebGestureEvent& fling_start_event, + const gfx::Vector2dF& velocity); + GestureEventQueue* gesture_event_queue_; + FlingControllerClient* client_; + // An object tracking the state of touchpad on the delivery of mouse events to // the renderer to filter mouse immediately after a touchpad fling canceling // tap. @@ -59,9 +123,24 @@ // canceling tap. TouchscreenTapSuppressionController touchscreen_tap_suppression_controller_; + // Gesture curve of the current active fling. + std::unique_ptr<blink::WebGestureCurve> fling_curve_; + + ActiveFlingParameters current_fling_parameters_; + + // True while no GestureFlingCancel has arrived after the FlingController has + // processed a GestureFlingStart. + bool fling_in_progress_; + + // Whether an active fling has seen a |ProgressFling()| call. This is useful + // for determining if the fling start time should be re-initialized. + bool has_fling_animation_started_; + + bool send_wheel_events_nonblocking_; + DISALLOW_COPY_AND_ASSIGN(FlingController); }; } // namespace content -#endif // FLING_CONTROLLER_H_ +#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_FLING_CONTROLLER_H_
diff --git a/content/browser/renderer_host/input/fling_controller_unittest.cc b/content/browser/renderer_host/input/fling_controller_unittest.cc new file mode 100644 index 0000000..2fb8725 --- /dev/null +++ b/content/browser/renderer_host/input/fling_controller_unittest.cc
@@ -0,0 +1,252 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/input/fling_controller.h" + +#include "base/run_loop.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/scoped_task_environment.h" +#include "content/browser/renderer_host/input/gesture_event_queue.h" +#include "content/public/common/content_features.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/events/base_event_utils.h" +#include "ui/events/blink/fling_booster.h" + +using blink::WebGestureEvent; +using blink::WebInputEvent; +using blink::WebMouseWheelEvent; + +namespace { +void GiveItSomeTime(uint64_t delay_in_ms) { + base::RunLoop run_loop; + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, run_loop.QuitClosure(), + base::TimeDelta::FromMillisecondsD(delay_in_ms)); + run_loop.Run(); +} +} // namespace + +namespace content { + +class FakeFlingController : public FlingController { + public: + FakeFlingController(GestureEventQueue* gesture_event_queue, + TouchpadTapSuppressionControllerClient* touchpad_client, + FlingControllerClient* fling_client, + const Config& config) + : FlingController(gesture_event_queue, + touchpad_client, + fling_client, + config) {} + + bool FlingBoosted() const { return fling_booster_->fling_boosted(); } +}; + +class FlingControllerTest : public testing::Test, + public TouchpadTapSuppressionControllerClient, + public GestureEventQueueClient, + public FlingControllerClient { + public: + // testing::Test + FlingControllerTest() + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::UI) {} + + ~FlingControllerTest() override {} + + void SetUp() override { + queue_ = std::make_unique<GestureEventQueue>(this, this, this, + GestureEventQueue::Config()); + fling_controller_ = std::make_unique<FakeFlingController>( + queue_.get(), this, this, FlingController::Config()); + feature_list_.InitFromCommandLine( + features::kTouchpadAndWheelScrollLatching.name, ""); + } + + // TouchpadTapSuppressionControllerClient + void SendMouseEventImmediately( + const MouseEventWithLatencyInfo& event) override {} + + // GestureEventQueueClient + void SendGestureEventImmediately( + const GestureEventWithLatencyInfo& event) override {} + void OnGestureEventAck(const GestureEventWithLatencyInfo& event, + InputEventAckSource ack_source, + InputEventAckState ack_result) override {} + + // FlingControllerClient + void SendGeneratedWheelEvent( + const MouseWheelEventWithLatencyInfo& wheel_event) override { + last_sent_wheel_ = wheel_event.event; + } + void SetNeedsBeginFrameForFlingProgress() override { + DCHECK(!scheduled_next_fling_progress_); + scheduled_next_fling_progress_ = true; + } + + void SimulateFlingStart(blink::WebGestureDevice source_device, + const gfx::Vector2dF& velocity) { + scheduled_next_fling_progress_ = false; + WebGestureEvent fling_start( + WebInputEvent::kGestureFlingStart, 0, + ui::EventTimeStampToSeconds(base::TimeTicks::Now())); + fling_start.source_device = source_device; + fling_start.data.fling_start.velocity_x = velocity.x(); + fling_start.data.fling_start.velocity_y = velocity.y(); + GestureEventWithLatencyInfo fling_start_with_latency(fling_start); + if (!fling_controller_->FilterGestureEvent(fling_start_with_latency)) + fling_controller_->ProcessGestureFlingStart(fling_start_with_latency); + } + + void SimulateFlingCancel(blink::WebGestureDevice source_device) { + WebGestureEvent fling_cancel( + WebInputEvent::kGestureFlingCancel, 0, + ui::EventTimeStampToSeconds(base::TimeTicks::Now())); + fling_cancel.source_device = source_device; + GestureEventWithLatencyInfo fling_cancel_with_latency(fling_cancel); + last_fling_cancel_filtered_ = + fling_controller_->FilterGestureEvent(fling_cancel_with_latency); + if (!last_fling_cancel_filtered_) + fling_controller_->ProcessGestureFlingCancel(fling_cancel_with_latency); + } + + void ProgressFling() { + DCHECK(scheduled_next_fling_progress_); + scheduled_next_fling_progress_ = false; + fling_controller_->ProgressFling(base::TimeTicks::Now()); + } + + bool FlingInProgress() { return fling_controller_->fling_in_progress(); } + bool FlingBoosted() { return fling_controller_->FlingBoosted(); } + + protected: + std::unique_ptr<FakeFlingController> fling_controller_; + WebMouseWheelEvent last_sent_wheel_; + bool last_fling_cancel_filtered_; + bool scheduled_next_fling_progress_; + + private: + base::test::ScopedTaskEnvironment scoped_task_environment_; + std::unique_ptr<GestureEventQueue> queue_; + base::test::ScopedFeatureList feature_list_; +}; + +TEST_F(FlingControllerTest, ControllerSendsWheelEndOnFlingWithZeroVelocity) { + SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF()); + // The controller doesn't start a fling and sends a wheel end event + // immediately. + EXPECT_FALSE(FlingInProgress()); + EXPECT_EQ(WebMouseWheelEvent::kPhaseEnded, last_sent_wheel_.momentum_phase); + EXPECT_EQ(0.f, last_sent_wheel_.delta_x); + EXPECT_EQ(0.f, last_sent_wheel_.delta_y); +} + +// TODO(crbug.com/795617): Test timing expectations make it flaky. +TEST_F(FlingControllerTest, DISABLED_ControllerHandlesGestureFling) { + SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(1000, 0)); + EXPECT_TRUE(FlingInProgress()); + // The first wheel event must have momentum_phase == KPhaseBegan. + GiveItSomeTime(17); + ProgressFling(); + EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, last_sent_wheel_.momentum_phase); + EXPECT_GT(last_sent_wheel_.delta_x, 0.f); + + // The rest of the wheel events must have momentum_phase == KPhaseChanged. + GiveItSomeTime(17); + ProgressFling(); + EXPECT_EQ(WebMouseWheelEvent::kPhaseChanged, last_sent_wheel_.momentum_phase); + EXPECT_GT(last_sent_wheel_.delta_x, 0.f); + + // Now cancel the fling. The GFC will get suppressed by fling booster. + SimulateFlingCancel(blink::kWebGestureDeviceTouchpad); + EXPECT_TRUE(last_fling_cancel_filtered_); + EXPECT_TRUE(FlingInProgress()); + + // Wait for the boosting timer to expire. The delayed cancelation must work. + GiveItSomeTime(500); + ProgressFling(); + EXPECT_FALSE(FlingInProgress()); + EXPECT_EQ(WebMouseWheelEvent::kPhaseEnded, last_sent_wheel_.momentum_phase); + EXPECT_EQ(0.f, last_sent_wheel_.delta_x); + EXPECT_EQ(0.f, last_sent_wheel_.delta_y); +} + +// TODO(crbug.com/795617): Test timing expectations make it flaky. +TEST_F(FlingControllerTest, DISABLED_ControllerSendsWheelEndWhenFlingIsOver) { + SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(100, 0)); + EXPECT_TRUE(FlingInProgress()); + GiveItSomeTime(17); + ProgressFling(); + EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, last_sent_wheel_.momentum_phase); + EXPECT_GT(last_sent_wheel_.delta_x, 0.f); + + GiveItSomeTime(17); + ProgressFling(); + while (FlingInProgress()) { + EXPECT_EQ(WebMouseWheelEvent::kPhaseChanged, + last_sent_wheel_.momentum_phase); + EXPECT_GT(last_sent_wheel_.delta_x, 0.f); + GiveItSomeTime(17); + ProgressFling(); + } + + EXPECT_EQ(WebMouseWheelEvent::kPhaseEnded, last_sent_wheel_.momentum_phase); + EXPECT_EQ(0.f, last_sent_wheel_.delta_x); + EXPECT_EQ(0.f, last_sent_wheel_.delta_y); +} + +// TODO(crbug.com/795617): Test timing expectations make it flaky. +TEST_F(FlingControllerTest, + DISABLED_EarlyFlingCancelationOnInertialGSUAckNotConsumed) { + SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(1000, 0)); + EXPECT_TRUE(FlingInProgress()); + GiveItSomeTime(17); + ProgressFling(); + EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, last_sent_wheel_.momentum_phase); + EXPECT_GT(last_sent_wheel_.delta_x, 0.f); + + // A non-consumed GSU ack in inertial state cancels out the rest of the fling. + WebGestureEvent scroll_update( + WebInputEvent::kGestureScrollUpdate, 0, + ui::EventTimeStampToSeconds(base::TimeTicks::Now())); + scroll_update.data.scroll_update.inertial_phase = + WebGestureEvent::kMomentumPhase; + + fling_controller_->OnGestureEventAck( + GestureEventWithLatencyInfo(scroll_update), + INPUT_EVENT_ACK_STATE_NOT_CONSUMED); + EXPECT_FALSE(FlingInProgress()); + EXPECT_EQ(WebMouseWheelEvent::kPhaseEnded, last_sent_wheel_.momentum_phase); + EXPECT_EQ(0.f, last_sent_wheel_.delta_x); + EXPECT_EQ(0.f, last_sent_wheel_.delta_y); +} + +// TODO(crbug.com/795617): Test timing expectations make it flaky. +TEST_F(FlingControllerTest, DISABLED_ControllerBoostsFling) { + SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(1000, 0)); + EXPECT_TRUE(FlingInProgress()); + // The first wheel event must have momentum_phase == KPhaseBegan. + GiveItSomeTime(17); + ProgressFling(); + EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, last_sent_wheel_.momentum_phase); + EXPECT_GT(last_sent_wheel_.delta_x, 0.f); + + // The rest of the wheel events must have momentum_phase == KPhaseChanged. + GiveItSomeTime(17); + ProgressFling(); + EXPECT_EQ(WebMouseWheelEvent::kPhaseChanged, last_sent_wheel_.momentum_phase); + EXPECT_GT(last_sent_wheel_.delta_x, 0.f); + + // Now cancel the fling. The GFC will get suppressed by fling booster. + SimulateFlingCancel(blink::kWebGestureDeviceTouchpad); + EXPECT_TRUE(last_fling_cancel_filtered_); + EXPECT_TRUE(FlingInProgress()); + + // The second GFS will boost the current active fling. + SimulateFlingStart(blink::kWebGestureDeviceTouchpad, gfx::Vector2dF(1000, 0)); + EXPECT_TRUE(FlingInProgress()); + EXPECT_TRUE(FlingBoosted()); +} + +} // namespace content
diff --git a/content/browser/renderer_host/input/gesture_event_queue.cc b/content/browser/renderer_host/input/gesture_event_queue.cc index 2044321..b4a1227 100644 --- a/content/browser/renderer_host/input/gesture_event_queue.cc +++ b/content/browser/renderer_host/input/gesture_event_queue.cc
@@ -27,6 +27,7 @@ GestureEventQueue::GestureEventQueue( GestureEventQueueClient* client, TouchpadTapSuppressionControllerClient* touchpad_client, + FlingControllerClient* fling_client, const Config& config) : client_(client), fling_in_progress_(false), @@ -35,9 +36,13 @@ allow_multiple_inflight_events_( base::FeatureList::IsEnabled(features::kVsyncAlignedInputEvents)), debounce_interval_(config.debounce_interval), - fling_controller_(this, touchpad_client, config.fling_config) { + fling_controller_(this, + touchpad_client, + fling_client, + config.fling_config) { DCHECK(client); DCHECK(touchpad_client); + DCHECK(fling_client); } GestureEventQueue::~GestureEventQueue() { } @@ -50,11 +55,40 @@ return; } + // fling_controller_ is in charge of handling GFS events from touchpad source + // when wheel scroll latching is enabled. In this case instead of queuing the + // GFS event to be sent to the renderer, the controller processes the fling + // and generates wheel events with momentum phase which are handled in the + // renderer normally. + if (gesture_event.event.GetType() == WebInputEvent::kGestureFlingStart && + gesture_event.event.source_device == blink::kWebGestureDeviceTouchpad) { + fling_controller_.ProcessGestureFlingStart(gesture_event); + fling_in_progress_ = true; + return; + } + + // If the GestureFlingStart event is processed by the fling_controller_, the + // GestureFlingCancel event should be the same. + if (gesture_event.event.GetType() == WebInputEvent::kGestureFlingCancel && + fling_controller_.fling_in_progress()) { + fling_controller_.ProcessGestureFlingCancel(gesture_event); + fling_in_progress_ = false; + return; + } + QueueAndForwardIfNecessary(gesture_event); } +void GestureEventQueue::ProgressFling(base::TimeTicks current_time) { + fling_controller_.ProgressFling(current_time); +} + bool GestureEventQueue::ShouldDiscardFlingCancelEvent( const GestureEventWithLatencyInfo& gesture_event) const { + // When the GFS is processed by the fling_controller_ the controller handles + // GFC filtering as well. + DCHECK(!(fling_controller_.fling_in_progress())); + if (coalesced_gesture_events_.empty() && fling_in_progress_) return false; GestureQueueWithAckState::const_reverse_iterator it = @@ -73,6 +107,13 @@ const GestureEventWithLatencyInfo& gesture_event) { if (debounce_interval_ <= base::TimeDelta()) return true; + + // Don't debounce any gesture events while a fling is in progress on the + // browser side. A GSE event in this case ends fling progress and it shouldn't + // get cancelled by its next GSB event. + if (fling_controller_.fling_in_progress()) + return true; + switch (gesture_event.event.GetType()) { case WebInputEvent::kGestureScrollUpdate: if (fling_in_progress_) @@ -225,12 +266,7 @@ // can be coalesced with existing queued events prior to dispatch. client_->OnGestureEventAck(event_with_latency, ack_source, ack_result); - const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result); - if (event_with_latency.event.GetType() == - WebInputEvent::kGestureFlingCancel) { - fling_controller_.GestureFlingCancelAck( - event_with_latency.event.source_device, processed); - } + fling_controller_.OnGestureEventAck(event_with_latency, ack_result); } void GestureEventQueue::LegacyProcessGestureAck( @@ -261,11 +297,8 @@ // can be coalesced with existing queued events prior to dispatch. client_->OnGestureEventAck(event_with_latency, ack_source, ack_result); - const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result); - if (type == WebInputEvent::kGestureFlingCancel) { - fling_controller_.GestureFlingCancelAck( - event_with_latency.event.source_device, processed); - } + fling_controller_.OnGestureEventAck(event_with_latency, ack_result); + DCHECK_LT(event_index, coalesced_gesture_events_.size()); coalesced_gesture_events_.erase(coalesced_gesture_events_.begin() + event_index);
diff --git a/content/browser/renderer_host/input/gesture_event_queue.h b/content/browser/renderer_host/input/gesture_event_queue.h index a6bf36a5..ac7cd2d 100644 --- a/content/browser/renderer_host/input/gesture_event_queue.h +++ b/content/browser/renderer_host/input/gesture_event_queue.h
@@ -73,6 +73,7 @@ // Both |client| and |touchpad_client| must outlive the GestureEventQueue. GestureEventQueue(GestureEventQueueClient* client, TouchpadTapSuppressionControllerClient* touchpad_client, + FlingControllerClient* fling_client, const Config& config); ~GestureEventQueue(); @@ -108,6 +109,10 @@ bool ShouldDiscardFlingCancelEvent( const GestureEventWithLatencyInfo& gesture_event) const; + // Calls |fling_controller_.ProgressFling| to advance an active fling on every + // begin frame. + void ProgressFling(base::TimeTicks current_time); + void set_debounce_interval_time_ms_for_testing(int interval_ms) { debounce_interval_ = base::TimeDelta::FromMilliseconds(interval_ms); } @@ -174,8 +179,8 @@ // The receiver of all forwarded gesture events. GestureEventQueueClient* client_; - // True if a GestureFlingStart is in progress on the renderer or - // queued without a subsequent queued GestureFlingCancel event. + // True if a GestureFlingStart is in progress or queued without a subsequent + // queued GestureFlingCancel event. bool fling_in_progress_; // True if a GestureScrollUpdate sequence is in progress.
diff --git a/content/browser/renderer_host/input/gesture_event_queue_unittest.cc b/content/browser/renderer_host/input/gesture_event_queue_unittest.cc index 78c5ba6..bb50f40 100644 --- a/content/browser/renderer_host/input/gesture_event_queue_unittest.cc +++ b/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
@@ -36,7 +36,8 @@ class GestureEventQueueTest : public testing::Test, public GestureEventQueueClient, - public TouchpadTapSuppressionControllerClient { + public TouchpadTapSuppressionControllerClient, + public FlingControllerClient { public: GestureEventQueueTest() : GestureEventQueueTest(false) {} @@ -55,7 +56,7 @@ // testing::Test void SetUp() override { - queue_.reset(new GestureEventQueue(this, this, DefaultConfig())); + queue_.reset(new GestureEventQueue(this, this, this, DefaultConfig())); } void TearDown() override { @@ -75,7 +76,7 @@ gesture_config.fling_config.touchscreen_tap_suppression_config .max_tap_gap_time = base::TimeDelta::FromMilliseconds(max_tap_gap_time_ms); - queue_.reset(new GestureEventQueue(this, this, gesture_config)); + queue_.reset(new GestureEventQueue(this, this, this, gesture_config)); } // GestureEventQueueClient @@ -104,6 +105,11 @@ void SendMouseEventImmediately( const MouseEventWithLatencyInfo& event) override {} + // FlingControllerClient + void SendGeneratedWheelEvent( + const MouseWheelEventWithLatencyInfo& wheel_event) override {} + void SetNeedsBeginFrameForFlingProgress() override {} + protected: static GestureEventQueue::Config DefaultConfig() { return GestureEventQueue::Config(); @@ -995,6 +1001,11 @@ TEST_P(GestureEventQueueWithSourceTest, GestureFlingCancelsFiltered) { WebGestureDevice source_device = GetParam(); + // GFS and GFC events with touchpad source are not queued since fling + // controller handles them. + if (source_device == blink::kWebGestureDeviceTouchpad) + return; + // GFC without previous GFS is dropped. SimulateGestureEvent(WebInputEvent::kGestureFlingCancel, source_device); EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); @@ -1159,18 +1170,20 @@ EXPECT_EQ(1U, GestureEventQueueSize()); EXPECT_EQ(1U, GestureEventDebouncingQueueSize()); - // The deferred events are correctly queued in coalescing queue. + // The deferred events are correctly queued in coalescing queue. The GFS with + // touchpad source is not queued since it is handled by fling controller. SimulateGestureFlingStartEvent(0, 10, blink::kWebGestureDeviceTouchpad); EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); - EXPECT_EQ(3U, GestureEventQueueSize()); + EXPECT_EQ(2U, GestureEventQueueSize()); EXPECT_EQ(0U, GestureEventDebouncingQueueSize()); EXPECT_FALSE(ScrollingInProgress()); EXPECT_TRUE(FlingInProgress()); + // While fling is in progress events don't get debounced. SimulateGestureEvent(WebInputEvent::kGestureScrollBegin, blink::kWebGestureDeviceTouchpad); EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); - EXPECT_EQ(4U, GestureEventQueueSize()); + EXPECT_EQ(3U, GestureEventQueueSize()); EXPECT_EQ(0U, GestureEventDebouncingQueueSize()); SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate, @@ -1186,9 +1199,9 @@ EXPECT_EQ(0U, GestureEventDebouncingQueueSize()); // Verify that the coalescing queue contains the correct events. - WebInputEvent::Type expected[] = { - WebInputEvent::kGestureScrollUpdate, WebInputEvent::kGestureScrollEnd, - WebInputEvent::kGestureFlingStart, WebInputEvent::kGestureScrollBegin}; + WebInputEvent::Type expected[] = {WebInputEvent::kGestureScrollUpdate, + WebInputEvent::kGestureScrollEnd, + WebInputEvent::kGestureScrollBegin}; for (unsigned i = 0; i < sizeof(expected) / sizeof(WebInputEvent::Type); i++) {
diff --git a/content/browser/renderer_host/input/input_router.h b/content/browser/renderer_host/input/input_router.h index 68a5493..175028b 100644 --- a/content/browser/renderer_host/input/input_router.h +++ b/content/browser/renderer_host/input/input_router.h
@@ -66,6 +66,9 @@ // Associate this InputRouter with a remote host channel. virtual void BindHost(mojom::WidgetInputHandlerHostRequest request, bool frame_handler) = 0; + + // Used to progress an active fling on every begin frame. + virtual void ProgressFling(base::TimeTicks current_time) = 0; }; } // namespace content
diff --git a/content/browser/renderer_host/input/input_router_client.h b/content/browser/renderer_host/input/input_router_client.h index 41afa6e..69a26a1 100644 --- a/content/browser/renderer_host/input/input_router_client.h +++ b/content/browser/renderer_host/input/input_router_client.h
@@ -60,6 +60,17 @@ virtual void ForwardGestureEventWithLatencyInfo( const blink::WebGestureEvent& gesture_event, const ui::LatencyInfo& latency_info) = 0; + + // Called when the input router generates a wheel event. It is intended that + // the client will do some processing on |wheel_event| and then send it back + // to the InputRouter via SendWheelEvent. + virtual void ForwardWheelEventWithLatencyInfo( + const blink::WebMouseWheelEvent& wheel_event, + const ui::LatencyInfo& latency_info) = 0; + + // Called when the input router needs a begin frame to advance an active + // fling. + virtual void SetNeedsBeginFrameForFlingProgress() = 0; }; } // namespace content
diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc index 2f3ded5..95ab2d5 100644 --- a/content/browser/renderer_host/input/input_router_impl.cc +++ b/content/browser/renderer_host/input/input_router_impl.cc
@@ -82,7 +82,7 @@ wheel_scroll_latching_enabled_(base::FeatureList::IsEnabled( features::kTouchpadAndWheelScrollLatching)), wheel_event_queue_(this, wheel_scroll_latching_enabled_), - gesture_event_queue_(this, this, config.gesture_config), + gesture_event_queue_(this, this, this, config.gesture_config), device_scale_factor_(1.f), host_binding_(this), frame_host_binding_(this), @@ -203,6 +203,10 @@ } } +void InputRouterImpl::ProgressFling(base::TimeTicks current_time) { + gesture_event_queue_.ProgressFling(current_time); +} + void InputRouterImpl::CancelTouchTimeout() { touch_event_queue_->SetAckTimeoutEnabled(false); } @@ -344,6 +348,16 @@ disposition_handler_->OnGestureEventAck(event, ack_source, ack_result); } +void InputRouterImpl::SendGeneratedWheelEvent( + const MouseWheelEventWithLatencyInfo& wheel_event) { + client_->ForwardWheelEventWithLatencyInfo(wheel_event.event, + wheel_event.latency); +} + +void InputRouterImpl::SetNeedsBeginFrameForFlingProgress() { + client_->SetNeedsBeginFrameForFlingProgress(); +} + void InputRouterImpl::SendMouseWheelEventImmediately( const MouseWheelEventWithLatencyInfo& wheel_event) { mojom::WidgetInputHandler::DispatchEventCallback callback = base::BindOnce(
diff --git a/content/browser/renderer_host/input/input_router_impl.h b/content/browser/renderer_host/input/input_router_impl.h index 1b19697..a7755f5 100644 --- a/content/browser/renderer_host/input/input_router_impl.h +++ b/content/browser/renderer_host/input/input_router_impl.h
@@ -51,6 +51,7 @@ class CONTENT_EXPORT InputRouterImpl : public InputRouter, public GestureEventQueueClient, + public FlingControllerClient, public MouseWheelEventQueueClient, public TouchEventQueueClient, public TouchpadTapSuppressionControllerClient, @@ -78,6 +79,7 @@ cc::TouchAction AllowedTouchAction() override; void BindHost(mojom::WidgetInputHandlerHostRequest request, bool frame_handler) override; + void ProgressFling(base::TimeTicks current_time) override; // InputHandlerHost impl void CancelTouchTimeout() override; @@ -119,6 +121,11 @@ InputEventAckSource ack_source, InputEventAckState ack_result) override; + // FlingControllerClient + void SendGeneratedWheelEvent( + const MouseWheelEventWithLatencyInfo& wheel_event) override; + void SetNeedsBeginFrameForFlingProgress() override; + // MouseWheelEventQueueClient void SendMouseWheelEventImmediately( const MouseWheelEventWithLatencyInfo& touch_event) override;
diff --git a/content/browser/renderer_host/input/input_router_impl_unittest.cc b/content/browser/renderer_host/input/input_router_impl_unittest.cc index b56b681f..ce0603f 100644 --- a/content/browser/renderer_host/input/input_router_impl_unittest.cc +++ b/content/browser/renderer_host/input/input_router_impl_unittest.cc
@@ -145,6 +145,17 @@ void DidStopFlinging() override { input_router_client_.DidStopFlinging(); } + void SetNeedsBeginFrameForFlingProgress() override { + input_router_client_.SetNeedsBeginFrameForFlingProgress(); + } + + void ForwardWheelEventWithLatencyInfo( + const blink::WebMouseWheelEvent& wheel_event, + const ui::LatencyInfo& latency_info) override { + input_router_client_.ForwardWheelEventWithLatencyInfo(wheel_event, + latency_info); + } + void ForwardGestureEventWithLatencyInfo( const blink::WebGestureEvent& gesture_event, const ui::LatencyInfo& latency_info) override { @@ -2325,9 +2336,19 @@ } TEST_F(InputRouterImplScaleGestureEventTest, GestureFlingStart) { + // Simulate a GSB since touchscreen flings must happen inside scroll. + SimulateGestureEvent(SyntheticWebGestureEventBuilder::BuildScrollBegin( + 10.f, 20.f, blink::kWebGestureDeviceTouchscreen)); + FlushGestureEvent(WebInputEvent::kGestureScrollBegin); + const gfx::Point orig(10, 20), scaled(20, 40); WebGestureEvent event = BuildGestureEvent(WebInputEvent::kGestureFlingStart, orig); + // Set the source device to touchscreen to make sure that the event gets + // dispatched to the renderer. When wheel scroll latching is enabled touchpad + // flings are not dispatched to the renderer, instead they are handled on the + // browser side. + event.source_device = blink::kWebGestureDeviceTouchscreen; event.data.fling_start.velocity_x = 30; event.data.fling_start.velocity_y = 40; SimulateGestureEvent(event);
diff --git a/content/browser/renderer_host/input/legacy_input_router_impl.cc b/content/browser/renderer_host/input/legacy_input_router_impl.cc index aac5baa..e277ce8 100644 --- a/content/browser/renderer_host/input/legacy_input_router_impl.cc +++ b/content/browser/renderer_host/input/legacy_input_router_impl.cc
@@ -65,7 +65,7 @@ wheel_scroll_latching_enabled_(base::FeatureList::IsEnabled( features::kTouchpadAndWheelScrollLatching)), wheel_event_queue_(this, wheel_scroll_latching_enabled_), - gesture_event_queue_(this, this, config.gesture_config), + gesture_event_queue_(this, this, this, config.gesture_config), device_scale_factor_(1.f) { touch_event_queue_.reset( new PassthroughTouchEventQueue(this, config.touch_config)); @@ -208,6 +208,10 @@ NOTREACHED(); } +void LegacyInputRouterImpl::ProgressFling(base::TimeTicks current_time) { + gesture_event_queue_.ProgressFling(current_time); +} + bool LegacyInputRouterImpl::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(LegacyInputRouterImpl, message) @@ -275,6 +279,16 @@ client_->ForwardGestureEventWithLatencyInfo(event, latency_info); } +void LegacyInputRouterImpl::SendGeneratedWheelEvent( + const MouseWheelEventWithLatencyInfo& wheel_event) { + client_->ForwardWheelEventWithLatencyInfo(wheel_event.event, + wheel_event.latency); +} + +void LegacyInputRouterImpl::SetNeedsBeginFrameForFlingProgress() { + client_->SetNeedsBeginFrameForFlingProgress(); +} + void LegacyInputRouterImpl::SendMouseWheelEventImmediately( const MouseWheelEventWithLatencyInfo& wheel_event) { FilterAndSendWebInputEvent(wheel_event.event, wheel_event.latency);
diff --git a/content/browser/renderer_host/input/legacy_input_router_impl.h b/content/browser/renderer_host/input/legacy_input_router_impl.h index be84b53..2104924c 100644 --- a/content/browser/renderer_host/input/legacy_input_router_impl.h +++ b/content/browser/renderer_host/input/legacy_input_router_impl.h
@@ -47,6 +47,7 @@ class CONTENT_EXPORT LegacyInputRouterImpl : public InputRouter, public GestureEventQueueClient, + public FlingControllerClient, public MouseWheelEventQueueClient, public TouchEventQueueClient, public TouchpadTapSuppressionControllerClient { @@ -74,6 +75,7 @@ void SetDeviceScaleFactor(float device_scale_factor) override; void BindHost(mojom::WidgetInputHandlerHostRequest request, bool frame_handler) override; + void ProgressFling(base::TimeTicks current_time) override; // IPC::Listener bool OnMessageReceived(const IPC::Message& message) override; @@ -115,6 +117,11 @@ InputEventAckSource ack_source, InputEventAckState ack_result) override; + // FlingControllerClient + void SendGeneratedWheelEvent( + const MouseWheelEventWithLatencyInfo& wheel_event) override; + void SetNeedsBeginFrameForFlingProgress() override; + // MouseWheelEventQueueClient void SendMouseWheelEventImmediately( const MouseWheelEventWithLatencyInfo& touch_event) override;
diff --git a/content/browser/renderer_host/input/legacy_input_router_impl_perftest.cc b/content/browser/renderer_host/input/legacy_input_router_impl_perftest.cc index 5b495fb05..ab588af3 100644 --- a/content/browser/renderer_host/input/legacy_input_router_impl_perftest.cc +++ b/content/browser/renderer_host/input/legacy_input_router_impl_perftest.cc
@@ -99,9 +99,13 @@ void OnSetWhiteListedTouchAction( cc::TouchAction white_listed_touch_action) override {} void DidStopFlinging() override {} + void ForwardWheelEventWithLatencyInfo( + const blink::WebMouseWheelEvent& event, + const ui::LatencyInfo& latency_info) override {} void ForwardGestureEventWithLatencyInfo( const blink::WebGestureEvent& event, const ui::LatencyInfo& latency_info) override {} + void SetNeedsBeginFrameForFlingProgress() override {} }; class NullIPCSender : public IPC::Sender {
diff --git a/content/browser/renderer_host/input/legacy_input_router_impl_unittest.cc b/content/browser/renderer_host/input/legacy_input_router_impl_unittest.cc index b4d593b1..ac99402 100644 --- a/content/browser/renderer_host/input/legacy_input_router_impl_unittest.cc +++ b/content/browser/renderer_host/input/legacy_input_router_impl_unittest.cc
@@ -2288,9 +2288,19 @@ } TEST_F(LegacyInputRouterImplScaleGestureEventTest, GestureFlingStart) { + // Simulate a GSB since touchscreen flings must happen inside scroll. + SimulateGestureEvent(SyntheticWebGestureEventBuilder::BuildScrollBegin( + 10.f, 20.f, blink::kWebGestureDeviceTouchscreen)); + process_->sink().ClearMessages(); + const gfx::Point orig(10, 20), scaled(20, 40); WebGestureEvent event = BuildGestureEvent(WebInputEvent::kGestureFlingStart, orig); + // Set the source device to touchscreen to make sure that the event gets + // dispatched to the renderer. When wheel scroll latching is enabled touchpad + // flings are not dispatched to the renderer, instead they are handled on the + // browser side. + event.source_device = blink::kWebGestureDeviceTouchscreen; event.data.fling_start.velocity_x = 30; event.data.fling_start.velocity_y = 40; SimulateGestureEvent(event);
diff --git a/content/browser/renderer_host/input/mock_input_router_client.cc b/content/browser/renderer_host/input/mock_input_router_client.cc index a46a930..b3cbf79 100644 --- a/content/browser/renderer_host/input/mock_input_router_client.cc +++ b/content/browser/renderer_host/input/mock_input_router_client.cc
@@ -65,6 +65,8 @@ void MockInputRouterClient::DidStopFlinging() { } +void MockInputRouterClient::SetNeedsBeginFrameForFlingProgress() {} + void MockInputRouterClient::ForwardGestureEventWithLatencyInfo( const blink::WebGestureEvent& gesture_event, const ui::LatencyInfo& latency_info) { @@ -73,6 +75,15 @@ GestureEventWithLatencyInfo(gesture_event, latency_info)); } +void MockInputRouterClient::ForwardWheelEventWithLatencyInfo( + const blink::WebMouseWheelEvent& wheel_event, + const ui::LatencyInfo& latency_info) { + if (input_router_) { + input_router_->SendWheelEvent( + MouseWheelEventWithLatencyInfo(wheel_event, latency_info)); + } +} + bool MockInputRouterClient::GetAndResetFilterEventCalled() { bool filter_input_event_called = filter_input_event_called_; filter_input_event_called_ = false;
diff --git a/content/browser/renderer_host/input/mock_input_router_client.h b/content/browser/renderer_host/input/mock_input_router_client.h index 9626250..23b1c30 100644 --- a/content/browser/renderer_host/input/mock_input_router_client.h +++ b/content/browser/renderer_host/input/mock_input_router_client.h
@@ -33,6 +33,10 @@ void DidOverscroll(const ui::DidOverscrollParams& params) override; void OnSetWhiteListedTouchAction(cc::TouchAction touch_action) override; void DidStopFlinging() override; + void SetNeedsBeginFrameForFlingProgress() override; + void ForwardWheelEventWithLatencyInfo( + const blink::WebMouseWheelEvent& wheel_event, + const ui::LatencyInfo& latency_info) override; void ForwardGestureEventWithLatencyInfo( const blink::WebGestureEvent& gesture_event, const ui::LatencyInfo& latency_info) override;
diff --git a/content/browser/renderer_host/input/mouse_wheel_event_queue.cc b/content/browser/renderer_host/input/mouse_wheel_event_queue.cc index 7bbde1d..5d5bead 100644 --- a/content/browser/renderer_host/input/mouse_wheel_event_queue.cc +++ b/content/browser/renderer_host/input/mouse_wheel_event_queue.cc
@@ -220,9 +220,10 @@ // because the events generated will be a GSB (non-synthetic) and GSE // (non-synthetic). This situation arises when OSX generates double // phase end information. - bool empty_sequence = !needs_update && - needs_scroll_begin_when_scroll_latching_disabled_ && - current_phase_ended; + bool empty_sequence = + !needs_update && needs_scroll_begin_when_scroll_latching_disabled_ && + current_phase_ended && + !event_sent_for_gesture_ack_->event.has_synthetic_phase; if (needs_update || !empty_sequence) { if (needs_scroll_begin_when_scroll_latching_disabled_) { // If no GSB has been sent, it will be a non-synthetic GSB. @@ -270,11 +271,10 @@ } else if (scrolling_device_ == gesture_event.event.source_device && (gesture_event.event.GetType() == blink::WebInputEvent::kGestureScrollEnd || - gesture_event.event.GetType() == - blink::WebInputEvent::kGestureFlingStart)) { + (gesture_event.event.GetType() == + blink::WebInputEvent::kGestureFlingStart && + scrolling_device_ != blink::kWebGestureDeviceTouchpad))) { scrolling_device_ = blink::kWebGestureDeviceUninitialized; - if (enable_scroll_latching_) - scroll_in_progress_ = false; } }
diff --git a/content/browser/renderer_host/overscroll_controller.cc b/content/browser/renderer_host/overscroll_controller.cc index 3d9b66f0..6bc3f0f1 100644 --- a/content/browser/renderer_host/overscroll_controller.cc +++ b/content/browser/renderer_host/overscroll_controller.cc
@@ -10,6 +10,7 @@ #include "base/logging.h" #include "content/browser/renderer_host/overscroll_controller_delegate.h" #include "content/public/browser/overscroll_configuration.h" +#include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" namespace content { @@ -35,7 +36,9 @@ } // namespace -OverscrollController::OverscrollController() {} +OverscrollController::OverscrollController() + : wheel_scroll_latching_enabled_(base::FeatureList::IsEnabled( + features::kTouchpadAndWheelScrollLatching)) {} OverscrollController::~OverscrollController() {} @@ -192,13 +195,16 @@ event.GetType() != blink::WebInputEvent::kGestureFlingStart) return false; - // Avoid completing the action on GestureScrollEnd generated - // from the touchpad since it is sent based on a timeout not - // when the user has stopped interacting. if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd && overscroll_source_ == OverscrollSource::TOUCHPAD) { DCHECK(IsGestureEventFromTouchpad(event)); - return false; + // Complete the action for a GSE with touchpad source only when it is in + // momentumPhase. + const blink::WebGestureEvent gesture_event = + static_cast<const blink::WebGestureEvent&>(event); + if (gesture_event.data.scroll_end.inertial_phase != + blink::WebGestureEvent::kMomentumPhase) + return false; } if (!delegate_) @@ -268,18 +274,24 @@ bool event_processed = false; switch (event.GetType()) { case blink::WebInputEvent::kGestureScrollBegin: { - // Avoid resetting the state on GestureScrollBegin generated - // from the touchpad since it is sent based on a timeout. + // When wheel scroll latching is disabled avoid resetting the state on + // GestureScrollBegin generated from the touchpad since it is sent for + // every wheel event. if (overscroll_mode_ != OVERSCROLL_NONE && - !IsGestureEventFromTouchpad(event)) { + (!IsGestureEventFromTouchpad(event) || + wheel_scroll_latching_enabled_)) { SetOverscrollMode(OVERSCROLL_NONE, OverscrollSource::NONE); } break; } case blink::WebInputEvent::kGestureScrollEnd: { - // Avoid resetting the state on GestureScrollEnd generated - // from the touchpad since it is sent based on a timeout. - bool reset_scroll_state = !IsGestureEventFromTouchpad(event); + // Only reset the state on GestureScrollEnd generated from the touchpad + // when the scrolling is in inertial state. + const blink::WebGestureEvent gesture_event = + static_cast<const blink::WebGestureEvent&>(event); + bool reset_scroll_state = !IsGestureEventFromTouchpad(event) || + (gesture_event.data.scroll_end.inertial_phase == + blink::WebGestureEvent::kMomentumPhase); if (reset_scroll_state) ResetScrollState();
diff --git a/content/browser/renderer_host/overscroll_controller.h b/content/browser/renderer_host/overscroll_controller.h index 46bc8784..104865bd 100644 --- a/content/browser/renderer_host/overscroll_controller.h +++ b/content/browser/renderer_host/overscroll_controller.h
@@ -144,6 +144,8 @@ // owned by this controller. OverscrollControllerDelegate* delegate_ = nullptr; + bool wheel_scroll_latching_enabled_; + DISALLOW_COPY_AND_ASSIGN(OverscrollController); };
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 0962f46..d27e842 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1245,13 +1245,25 @@ bool is_for_guests_only) { if (g_render_process_host_factory_) { return g_render_process_host_factory_->CreateRenderProcessHost( - browser_context); + browser_context, site_instance); } if (!storage_partition_impl) { storage_partition_impl = static_cast<StoragePartitionImpl*>( BrowserContext::GetStoragePartition(browser_context, site_instance)); } + // If we've made a StoragePartition for guests (e.g., for the <webview> tag), + // stash the Site URL on it. This way, when we start a service worker inside + // this storage partition, we can create the appropriate SiteInstance for + // finding a process (e.g., we will try to start a worker from + // "https://example.com/sw.js" but need to use the site URL + // "chrome-guest://blahblah" to get a process in the guest's + // StoragePartition.) + if (is_for_guests_only && site_instance && + storage_partition_impl->site_for_service_worker().is_empty()) { + storage_partition_impl->set_site_for_service_worker( + site_instance->GetSiteURL()); + } return new RenderProcessHostImpl(browser_context, storage_partition_impl, is_for_guests_only);
diff --git a/content/browser/renderer_host/render_process_host_unittest.cc b/content/browser/renderer_host/render_process_host_unittest.cc index a6ecd7a..5a21892 100644 --- a/content/browser/renderer_host/render_process_host_unittest.cc +++ b/content/browser/renderer_host/render_process_host_unittest.cc
@@ -854,7 +854,7 @@ // Create a foo.com SiteInstance and check that its process does not // reuse the foo process from the first navigation, since it's now in a - // different StoragePartiiton. + // different StoragePartition. scoped_refptr<SiteInstanceImpl> site_instance = SiteInstanceImpl::CreateForURL(browser_context(), kUrl); site_instance->set_process_reuse_policy(
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index ff72e2b..4820248c 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -1179,18 +1179,36 @@ DCHECK(!is_in_gesture_scroll_[gesture_event.source_device]); is_in_gesture_scroll_[gesture_event.source_device] = true; } else if (gesture_event.GetType() == - blink::WebInputEvent::kGestureScrollEnd || - gesture_event.GetType() == - blink::WebInputEvent::kGestureFlingStart) { - DCHECK(is_in_gesture_scroll_[gesture_event.source_device] || - gesture_event.GetType() == blink::WebInputEvent::kGestureFlingStart); + blink::WebInputEvent::kGestureScrollEnd) { + DCHECK(is_in_gesture_scroll_[gesture_event.source_device]); is_in_gesture_scroll_[gesture_event.source_device] = false; - } + } else if (gesture_event.GetType() == + blink::WebInputEvent::kGestureFlingStart) { + if (gesture_event.source_device == + blink::WebGestureDevice::kWebGestureDeviceTouchpad) { + if (GetView()->wheel_scroll_latching_enabled()) { + // When wheel scroll latching is enabled, no GSE is sent before GFS, so + // is_in_gesture_scroll must be true. + DCHECK(is_in_gesture_scroll_[gesture_event.source_device]); - if (gesture_event.GetType() == blink::WebInputEvent::kGestureFlingStart && - gesture_event.source_device == - blink::WebGestureDevice::kWebGestureDeviceTouchpad) { - is_in_touchpad_gesture_fling_ = true; + // When wheel scroll latching is enabled GFS with touchpad source is + // handled by FlingController on browser side and GSU events with + // inertial phase will be sent to the renderer. Therefore, + // is_in_gesture_scroll must stay true till the fling progress is + // finished. Then the FlingController will generate and send a GSE event + // to show the end of a scroll sequence. + } else { + // When wheel scroll latching is disabled a GSE is sent before a GFS. + // The GSE has already finished the scroll sequence. + DCHECK(!is_in_gesture_scroll_[gesture_event.source_device]); + } + + is_in_touchpad_gesture_fling_ = true; + } else { // gesture_event.source_device != + // blink::WebGestureDevice::kWebGestureDeviceTouchpad + DCHECK(is_in_gesture_scroll_[gesture_event.source_device]); + is_in_gesture_scroll_[gesture_event.source_device] = false; + } } // TODO(wjmaclean) Remove the code for supporting resending gesture events @@ -2305,6 +2323,10 @@ view_->DidStopFlinging(); } +void RenderWidgetHostImpl::SetNeedsBeginFrameForFlingProgress() { + SetNeedsBeginFrame(true); +} + void RenderWidgetHostImpl::DispatchInputEventWithLatencyInfo( const blink::WebInputEvent& event, ui::LatencyInfo* latency) { @@ -2876,4 +2898,9 @@ } } +void RenderWidgetHostImpl::ProgressFling(base::TimeTicks current_time) { + if (input_router_) + input_router_->ProgressFling(current_time); +} + } // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index fae871cd..859dae15 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -385,9 +385,9 @@ const ui::LatencyInfo& latency); // Virtual for testing. void ForwardMouseEventWithLatencyInfo(const blink::WebMouseEvent& mouse_event, const ui::LatencyInfo& latency); - virtual void ForwardWheelEventWithLatencyInfo( + void ForwardWheelEventWithLatencyInfo( const blink::WebMouseWheelEvent& wheel_event, - const ui::LatencyInfo& latency); // Virtual for testing. + const ui::LatencyInfo& latency) override; // Returns an emulator for this widget. See TouchEmulator for more details. TouchEmulator* GetTouchEmulator(); @@ -627,6 +627,8 @@ const std::vector<gfx::Rect>& character_bounds) override; void OnImeCancelComposition() override; + void ProgressFling(base::TimeTicks current_time); + protected: // --------------------------------------------------------------------------- // The following method is overridden by RenderViewHost to send upwards to @@ -755,6 +757,7 @@ void DidStopFlinging() override; void OnSetWhiteListedTouchAction( cc::TouchAction white_listed_touch_action) override {} + void SetNeedsBeginFrameForFlingProgress() override; // Dispatch input events with latency information void DispatchInputEventWithLatencyInfo(const blink::WebInputEvent& event,
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc index 5f0a127..1d6941a 100644 --- a/content/browser/renderer_host/render_widget_host_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -123,6 +123,7 @@ void SetForceEnableZoom(bool enabled) override {} void BindHost(mojom::WidgetInputHandlerHostRequest request, bool frame_handler) override {} + void ProgressFling(base::TimeTicks time) override {} // IPC::Listener bool OnMessageReceived(const IPC::Message& message) override {
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 093c2961..283b6850 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -627,7 +627,8 @@ UpdateNeedsBeginFramesInternal(); } -void RenderWidgetHostViewAura::OnBeginFrame() { +void RenderWidgetHostViewAura::OnBeginFrame(base::TimeTicks frame_time) { + host_->ProgressFling(frame_time); UpdateNeedsBeginFramesInternal(); }
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 655981c..0de4a74 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -481,7 +481,7 @@ void OnTextSelectionChanged(TextInputManager* text_input_mangager, RenderWidgetHostViewBase* updated_view) override; - void OnBeginFrame(); + void OnBeginFrame(base::TimeTicks frame_time); // Detaches |this| from the input method object. void DetachFromInputMethod();
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 a706fff..9a97742 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
@@ -2007,29 +2007,24 @@ base::RunLoop().RunUntilIdle(); events = GetAndResetDispatchedMessages(); - EXPECT_EQ("GestureFlingStart", GetMessageNames(events)); - gesture_event = static_cast<const WebGestureEvent*>( - events[0]->ToEvent()->Event()->web_event.get()); - EXPECT_EQ(WebInputEvent::kGestureFlingStart, gesture_event->GetType()); - events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED); - SendNotConsumedAcks(events); + // A GFS with touchpad source won't get dispatched to the renderer. + EXPECT_EQ(0U, events.size()); - // Handling the next ui::ET_SCROLL event will send a fling cancellation and a - // mouse wheel with kPhaseBegan. + // Handling the next ui::ET_SCROLL event will generate a GFC which resets the + // phase state. The fling controller processes GFC and generates a wheel event + // with momentum_phase == kPhaseEnded. The mouse wheel created from scroll2 + // will have phase == kPhaseBegan. ui::ScrollEvent scroll2(ui::ET_SCROLL, gfx::Point(2, 2), ui::EventTimeForNow(), 0, 0, 15, 0, 15, 2); view_->OnScrollEvent(&scroll2); base::RunLoop().RunUntilIdle(); events = GetAndResetDispatchedMessages(); - EXPECT_EQ(2U, events.size()); - gesture_event = static_cast<const WebGestureEvent*>( - events[0]->ToEvent()->Event()->web_event.get()); - - EXPECT_EQ(WebInputEvent::kGestureFlingCancel, gesture_event->GetType()); - events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED); - + EXPECT_EQ("MouseWheel GestureScrollEnd MouseWheel", GetMessageNames(events)); wheel_event = static_cast<const WebMouseWheelEvent*>( - events[1]->ToEvent()->Event()->web_event.get()); + events[0]->ToEvent()->Event()->web_event.get()); + EXPECT_EQ(WebMouseWheelEvent::kPhaseEnded, wheel_event->momentum_phase); + wheel_event = static_cast<const WebMouseWheelEvent*>( + events[2]->ToEvent()->Event()->web_event.get()); EXPECT_EQ(WebMouseWheelEvent::kPhaseBegan, wheel_event->phase); } @@ -4426,31 +4421,37 @@ events = GetAndResetDispatchedMessages(); EXPECT_EQ(0U, events.size()); - // Send a fling start, but with a small velocity, so that the overscroll is - // aborted. The fling should proceed to the renderer, through the gesture - // event filter. - SimulateGestureEvent(WebInputEvent::kGestureScrollBegin, - blink::kWebGestureDeviceTouchscreen); - events = GetAndResetDispatchedMessages(); - EXPECT_EQ("GestureScrollBegin", GetMessageNames(events)); - SendScrollBeginAckIfNeeded(events, INPUT_EVENT_ACK_STATE_CONSUMED); + // Send a fling start, but with a small velocity, the fling controller handles + // GFS with touchpad source and the event doesn't get queued in gesture event + // queue. The overscroll state doesn't get reset till the first ProgressFling + // call. SimulateGestureFlingStartEvent(0.f, 0.1f, blink::kWebGestureDeviceTouchpad); events = GetAndResetDispatchedMessages(); + EXPECT_EQ(0U, events.size()); + EXPECT_EQ(OVERSCROLL_EAST, overscroll_mode()); + EXPECT_EQ(OverscrollSource::TOUCHPAD, overscroll_source()); + + // ProgressFling will send a nonblocking wheel end event. The generated GSE + // resets the overscroll state. + widget_host_->ProgressFling(base::TimeTicks::Now() + + base::TimeDelta::FromMilliseconds(20)); + EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode()); EXPECT_EQ(OverscrollSource::NONE, overscroll_source()); - - EXPECT_EQ("GestureFlingStart", GetMessageNames(events)); } +// TODO(crbug.com/795617): Test timing expectations make it flaky. TEST_F(RenderWidgetHostViewAuraOverscrollTest, - ScrollEventsOverscrollWithFling) { + DISABLED_ScrollEventsOverscrollWithFling) { ScrollEventsOverscrollWithFling(); } +// TODO(crbug.com/795617): Test timing expectations make it flaky. TEST_F(RenderWidgetHostViewAuraOverscrollWithoutWheelScrollLatchingTest, - ScrollEventsOverscrollWithFling) { + DISABLED_ScrollEventsOverscrollWithFling) { ScrollEventsOverscrollWithFling(); } +// TODO(crbug.com/795617): Test timing expectations make it flaky. TEST_F(RenderWidgetHostViewAuraOverScrollAsyncWheelEventsEnabledTest, - ScrollEventsOverscrollWithFling) { + DISABLED_ScrollEventsOverscrollWithFling) { ScrollEventsOverscrollWithFling(); } @@ -4521,20 +4522,24 @@ events = GetAndResetDispatchedMessages(); EXPECT_EQ(0U, events.size()); - // Send a fling start, but with a small velocity, so that the overscroll is - // aborted. The fling should proceed to the renderer, through the gesture - // event filter. - SimulateGestureEvent(WebInputEvent::kGestureScrollBegin, - blink::kWebGestureDeviceTouchscreen); + // Send a fling start, but with a zero velocity, the fling should not proceed + // to the renderer. + SimulateGestureFlingStartEvent(0.f, 0.f, blink::kWebGestureDeviceTouchpad); events = GetAndResetDispatchedMessages(); - EXPECT_EQ("GestureScrollBegin", GetMessageNames(events)); - SendScrollBeginAckIfNeeded(events, INPUT_EVENT_ACK_STATE_CONSUMED); - SimulateGestureFlingStartEvent(10.f, 0.f, blink::kWebGestureDeviceTouchpad); + for (const auto& event : events) { + EXPECT_NE(WebInputEvent::kGestureFlingStart, + event->ToEvent()->Event()->web_event->GetType()); + } + + // Fling controller handles the GFS with touchpad source and zero velocity and + // sends a nonblocking wheel end event. The GSE generated from wheel end event + // resets scroll state. + EXPECT_EQ( + WebInputEvent::kGestureScrollEnd, + events[events.size() - 1]->ToEvent()->Event()->web_event->GetType()); + EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode()); EXPECT_EQ(OverscrollSource::NONE, overscroll_source()); - - events = GetAndResetDispatchedMessages(); - EXPECT_EQ("GestureFlingStart", GetMessageNames(events)); } TEST_F(RenderWidgetHostViewAuraOverscrollTest, ScrollEventsOverscrollWithZeroFling) { @@ -5439,42 +5444,28 @@ events = ExpectGestureScrollEventsAfterMouseWheelACK(false, 0); } SendScrollUpdateAck(events, INPUT_EVENT_ACK_STATE_CONSUMED); - - if (wheel_scrolling_mode_ == kAsyncWheelEvents) { - SimulateWheelEventWithPhase(0, 0, 0, true, WebMouseWheelEvent::kPhaseEnded); - events = GetAndResetDispatchedMessages(); - EXPECT_EQ("MouseWheel GestureScrollEnd", GetMessageNames(events)); - } else if (wheel_scroll_latching_enabled_) { - SimulateWheelEventWithPhase(0, 0, 0, true, WebMouseWheelEvent::kPhaseEnded); - events = GetAndResetDispatchedMessages(); - EXPECT_EQ("MouseWheel", GetMessageNames(events)); - SendNotConsumedAcks(events); - events = ExpectGestureScrollEndForWheelScrolling(true); - } else { - events = ExpectGestureScrollEndForWheelScrolling(true); - } EXPECT_TRUE(ScrollStateIsContentScrolling()); - SendNotConsumedAcks(events); - // Touchpad scroll can end with a zero-velocity fling which is not dispatched, - // but it should still reset the overscroll controller state. - SimulateGestureEvent(WebInputEvent::kGestureScrollBegin, - blink::kWebGestureDeviceTouchscreen); - events = GetAndResetDispatchedMessages(); - EXPECT_EQ("GestureScrollBegin", GetMessageNames(events)); - SendScrollBeginAckIfNeeded(events, INPUT_EVENT_ACK_STATE_CONSUMED); + // Touchpad scroll can end with a zero-velocity fling which is not dispatched. SimulateGestureFlingStartEvent(0.f, 0.f, blink::kWebGestureDeviceTouchpad); + events = GetAndResetDispatchedMessages(); + for (const auto& event : events) { + EXPECT_NE(WebInputEvent::kGestureFlingStart, + event->ToEvent()->Event()->web_event->GetType()); + } + + // Fling controller handles a GFS with touchpad source and zero velocity and + // sends a nonblocking wheel end event. The GSE generated from wheel end event + // resets scroll state. + EXPECT_EQ( + WebInputEvent::kGestureScrollEnd, + events[events.size() - 1]->ToEvent()->Event()->web_event->GetType()); EXPECT_TRUE(ScrollStateIsUnknown()); // Dropped flings should neither propagate *nor* indicate that they were // consumed and have triggered a fling animation (as tracked by the router). EXPECT_FALSE(parent_host_->input_router()->HasPendingEvents()); - SimulateGestureEvent(WebInputEvent::kGestureScrollEnd, - blink::kWebGestureDeviceTouchscreen); - events = GetAndResetDispatchedMessages(); - EXPECT_EQ("GestureScrollEnd", GetMessageNames(events)); - SimulateWheelEventPossiblyIncludingPhase( -5, 0, 0, true, WebMouseWheelEvent::kPhaseBegan); // sent directly SimulateWheelEventPossiblyIncludingPhase( @@ -5503,33 +5494,26 @@ SendNotConsumedAcks(events); - if (wheel_scrolling_mode_ == kAsyncWheelEvents) { - SimulateWheelEventWithPhase(0, 0, 0, true, WebMouseWheelEvent::kPhaseEnded); - events = GetAndResetDispatchedMessages(); - EXPECT_EQ("MouseWheel GestureScrollEnd", GetMessageNames(events)); - } else if (wheel_scroll_latching_enabled_) { - SimulateWheelEventWithPhase(0, 0, 0, true, WebMouseWheelEvent::kPhaseEnded); - events = GetAndResetDispatchedMessages(); - EXPECT_EQ("MouseWheel", GetMessageNames(events)); - SendNotConsumedAcks(events); - events = ExpectGestureScrollEndForWheelScrolling(true); - } else { - events = ExpectGestureScrollEndForWheelScrolling(true); - } EXPECT_EQ(OVERSCROLL_WEST, overscroll_mode()); EXPECT_EQ(OverscrollSource::TOUCHPAD, overscroll_source()); EXPECT_TRUE(ScrollStateIsOverscrolling()); - // The GestureScrollBegin will reset the delegate's mode, so check it here. - EXPECT_EQ(OVERSCROLL_WEST, overscroll_delegate()->current_mode()); - SimulateGestureEvent(WebInputEvent::kGestureScrollBegin, - blink::kWebGestureDeviceTouchscreen); - events = GetAndResetDispatchedMessages(); - EXPECT_EQ("GestureScrollBegin", GetMessageNames(events)); - SendScrollBeginAckIfNeeded(events, INPUT_EVENT_ACK_STATE_CONSUMED); + // Touchpad scroll can end with a zero-velocity fling which is not dispatched. SimulateGestureFlingStartEvent(0.f, 0.f, blink::kWebGestureDeviceTouchpad); - SendNotConsumedAcks(events); events = GetAndResetDispatchedMessages(); + + for (const auto& event : events) { + EXPECT_NE(WebInputEvent::kGestureFlingStart, + event->ToEvent()->Event()->web_event->GetType()); + } + + // Fling controller handles a GFS with touchpad source and zero velocity and + // sends a nonblocking wheel end event. The GSE generated from wheel end event + // resets scroll state. + EXPECT_EQ( + WebInputEvent::kGestureScrollEnd, + events[events.size() - 1]->ToEvent()->Event()->web_event->GetType()); + EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode()); EXPECT_EQ(OverscrollSource::NONE, overscroll_source()); EXPECT_TRUE(ScrollStateIsUnknown()); @@ -5890,18 +5874,31 @@ EXPECT_EQ(15.f, overscroll_delta_x()); EXPECT_EQ(-5.f, overscroll_delta_y()); SimulateGestureFlingStartEvent(0.f, 0.1f, blink::kWebGestureDeviceTouchpad); + // Fling controller handles GFS with touchpad source and the event doesn't get + // queued in gesture event queue. + EXPECT_EQ(0U, events.size()); + + // The first ProgressFling will send a nonblocking wheel end event. The GSE + // generated from the wheel end event resets the overscroll state. + widget_host_->ProgressFling(base::TimeTicks::Now() + + base::TimeDelta::FromMilliseconds(20)); + EXPECT_EQ(0.f, overscroll_delta_x()); EXPECT_EQ(0.f, overscroll_delta_y()); } -TEST_F(RenderWidgetHostViewAuraOverscrollTest, ScrollDeltasResetOnEnd) { +// TODO(crbug.com/795617): Test timing expectations make it flaky. +TEST_F(RenderWidgetHostViewAuraOverscrollTest, + DISABLED_ScrollDeltasResetOnEnd) { ScrollDeltasResetOnEnd(); } +// TODO(crbug.com/795617): Test timing expectations make it flaky. TEST_F(RenderWidgetHostViewAuraOverscrollWithoutWheelScrollLatchingTest, - ScrollDeltasResetOnEnd) { + DISABLED_ScrollDeltasResetOnEnd) { ScrollDeltasResetOnEnd(); } +// TODO(crbug.com/795617): Test timing expectations make it flaky. TEST_F(RenderWidgetHostViewAuraOverScrollAsyncWheelEventsEnabledTest, - ScrollDeltasResetOnEnd) { + DISABLED_ScrollDeltasResetOnEnd) { ScrollDeltasResetOnEnd(); }
diff --git a/content/browser/renderer_host/render_widget_host_view_event_handler.cc b/content/browser/renderer_host/render_widget_host_view_event_handler.cc index a6a091c..bce27e7 100644 --- a/content/browser/renderer_host/render_widget_host_view_event_handler.cc +++ b/content/browser/renderer_host/render_widget_host_view_event_handler.cc
@@ -550,16 +550,20 @@ // the current scroll. mouse_wheel_phase_handler_.DispatchPendingWheelEndEvent(); mouse_wheel_phase_handler_.SendWheelEndIfNeeded(); - } else if (event->type() == ui::ET_GESTURE_SCROLL_END) { - // Make sure that the next wheel event will have phase = |kPhaseBegan|. - // This is for maintaining the correct phase info when some of the wheel - // events get ignored while a touchscreen scroll is going on. - mouse_wheel_phase_handler_.IgnorePendingWheelEndEvent(); - mouse_wheel_phase_handler_.ResetScrollSequence(); } else if (event->type() == ui::ET_SCROLL_FLING_START) { RecordAction(base::UserMetricsAction("TouchscreenScrollFling")); } + if (event->type() == ui::ET_GESTURE_SCROLL_END || + event->type() == ui::ET_SCROLL_FLING_START) { + // Scrolling with touchscreen has finished. Make sure that the next wheel + // event will have phase = |kPhaseBegan|. This is for maintaining the + // correct phase info when some of the wheel events get ignored while a + // touchscreen scroll is going on. + mouse_wheel_phase_handler_.IgnorePendingWheelEndEvent(); + mouse_wheel_phase_handler_.ResetScrollSequence(); + } + if (ShouldRouteEvent(event)) { host_->delegate()->GetInputEventRouter()->RouteGestureEvent( host_view_, &gesture, *event->latency());
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 67c8e279..ecfb5300 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.h +++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -22,8 +22,6 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" -#include "components/viz/common/surfaces/local_surface_id.h" -#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" #include "components/viz/common/surfaces/surface_id.h" #include "content/browser/renderer_host/browser_compositor_view_mac.h" #include "content/browser/renderer_host/input/mouse_wheel_phase_handler.h" @@ -500,7 +498,6 @@ // BrowserCompositorMacClient implementation. SkColor BrowserCompositorMacGetGutterColor(SkColor color) const override; void BrowserCompositorMacOnBeginFrame() override; - viz::LocalSurfaceId GetLocalSurfaceId() const override; void OnFrameTokenChanged(uint32_t frame_token) override; // AcceleratedWidgetMacNSView implementation. @@ -626,9 +623,6 @@ std::unique_ptr<CursorManager> cursor_manager_; - // The size associated with the current LocalSurfaceId if any. - gfx::Size last_size_; - enum class RepaintState { // No repaint in progress. None, @@ -640,13 +634,6 @@ ScreenUpdatesDisabled, } repaint_state_ = RepaintState::None; - // The last device scale factor associated with the current - // LocalSurfaceId if any. - float last_device_scale_factor_ = 0.f; - - viz::LocalSurfaceId local_surface_id_; - viz::ParentLocalSurfaceIdAllocator parent_local_surface_id_allocator_; - // Factory used to safely scope delayed calls to ShutdownHost(). base::WeakPtrFactory<RenderWidgetHostViewMac> weak_factory_;
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 b7e7a00..039e83e 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -396,10 +396,6 @@ UpdateNeedsBeginFramesInternal(); } -viz::LocalSurfaceId RenderWidgetHostViewMac::GetLocalSurfaceId() const { - return local_surface_id_; -} - void RenderWidgetHostViewMac::OnFrameTokenChanged(uint32_t frame_token) { OnFrameTokenChangedForView(frame_token); } @@ -456,7 +452,6 @@ viz::FrameSinkId frame_sink_id = render_widget_host_->AllocateFrameSinkId(is_guest_view_hack_); - local_surface_id_ = parent_local_surface_id_allocator_.GenerateId(); browser_compositor_.reset( new BrowserCompositorMac(this, this, render_widget_host_->is_hidden(), [cocoa_view_ window], frame_sink_id)); @@ -797,11 +792,6 @@ if (rect.size().IsEmpty()) return; - if (rect.size() != last_size_) { - local_surface_id_ = parent_local_surface_id_allocator_.GenerateId(); - last_size_ = rect.size(); - } - // Ignore the position of |rect| for non-popup rwhvs. This is because // background tabs do not have a window, but the window is required for the // coordinate conversions. Popups are always for a visible tab. @@ -1102,7 +1092,6 @@ if (!render_widget_host_ || !render_widget_host_->auto_resize_enabled()) return; - local_surface_id_ = parent_local_surface_id_allocator_.GenerateId(); render_widget_host_->DidAllocateLocalSurfaceIdForAutoResize( render_widget_host_->last_auto_resize_request_number()); browser_compositor_->WasResized(); @@ -1786,10 +1775,6 @@ return; if (changed_metrics & DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR) { - if (display.device_scale_factor() != last_device_scale_factor_) { - local_surface_id_ = parent_local_surface_id_allocator_.GenerateId(); - last_device_scale_factor_ = display.device_scale_factor(); - } RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(GetRenderWidgetHost()); if (host) {
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm index b575cb1..09ad9c3 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
@@ -131,7 +131,7 @@ TestBrowserContext browser_context; MockRenderProcessHostFactory process_host_factory; RenderProcessHost* process_host = - process_host_factory.CreateRenderProcessHost(&browser_context); + process_host_factory.CreateRenderProcessHost(&browser_context, nullptr); // Populates |g_supported_scale_factors|. std::vector<ui::ScaleFactor> supported_factors;
diff --git a/content/browser/renderer_host/text_input_client_mac_unittest.mm b/content/browser/renderer_host/text_input_client_mac_unittest.mm index 3f9607c..91fe5b7 100644 --- a/content/browser/renderer_host/text_input_client_mac_unittest.mm +++ b/content/browser/renderer_host/text_input_client_mac_unittest.mm
@@ -57,7 +57,7 @@ delegate_(), thread_("TextInputClientMacTestThread") { RenderProcessHost* rph = - process_factory_.CreateRenderProcessHost(&browser_context_); + process_factory_.CreateRenderProcessHost(&browser_context_, nullptr); int32_t routing_id = rph->GetNextRoutingID(); mojom::WidgetPtr widget; mock_widget_impl_ =
diff --git a/content/browser/renderer_interface_binders.cc b/content/browser/renderer_interface_binders.cc index 2d81357..2045833 100644 --- a/content/browser/renderer_interface_binders.cc +++ b/content/browser/renderer_interface_binders.cc
@@ -16,11 +16,13 @@ #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/storage_partition_impl.h" #include "content/browser/websockets/websocket_manager.h" +#include "content/network/restricted_cookie_manager.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" +#include "content/public/common/content_switches.h" #include "services/device/public/interfaces/constants.mojom.h" #include "services/device/public/interfaces/vibration_manager.mojom.h" #include "services/service_manager/public/cpp/binder_registry.h" @@ -85,6 +87,24 @@ connector->BindInterface(service_name, std::move(request)); } +void GetRestrictedCookieManager( + network::mojom::RestrictedCookieManagerRequest request, + RenderProcessHost* render_process_host, + const url::Origin& origin) { + if (!base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableExperimentalWebPlatformFeatures)) { + return; + } + + StoragePartition* storage_partition = + render_process_host->GetStoragePartition(); + mojom::NetworkContext* network_context = + storage_partition->GetNetworkContext(); + uint32_t render_process_id = render_process_host->GetID(); + network_context->GetRestrictedCookieManager( + std::move(request), render_process_id, MSG_ROUTING_NONE); +} + // Register renderer-exposed interfaces. Each registered interface binder is // exposed to all renderer-hosted execution context types (document/frame, // dedicated worker, shared worker and service worker) where the appropriate @@ -142,6 +162,8 @@ })); parameterized_binder_registry_.AddInterface( base::BindRepeating(&BackgroundFetchServiceImpl::Create)); + parameterized_binder_registry_.AddInterface( + base::BindRepeating(GetRestrictedCookieManager)); } RendererInterfaceBinders& GetRendererInterfaceBinders() {
diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc index 8f771b9..d633c46 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.cc +++ b/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -166,7 +166,8 @@ BrowserContext* browser_context) : core_observer_list_( new base::ObserverListThreadSafe<ServiceWorkerContextCoreObserver>()), - process_manager_(new ServiceWorkerProcessManager(browser_context)), + process_manager_( + std::make_unique<ServiceWorkerProcessManager>(browser_context)), is_incognito_(false), storage_partition_(nullptr), resource_context_(nullptr) { @@ -236,6 +237,7 @@ StoragePartitionImpl* storage_partition) { DCHECK_CURRENTLY_ON(BrowserThread::UI); storage_partition_ = storage_partition; + process_manager_->set_storage_partition(storage_partition_); } ResourceContext* ServiceWorkerContextWrapper::resource_context() {
diff --git a/content/browser/service_worker/service_worker_context_wrapper.h b/content/browser/service_worker/service_worker_context_wrapper.h index 63e2244..3dedf308 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.h +++ b/content/browser/service_worker/service_worker_context_wrapper.h
@@ -82,7 +82,7 @@ void DeleteAndStartOver(); // The StoragePartition should only be used on the UI thread. - // Can be null before/during init and during/after shutdown. + // Can be null before/during init and during/after shutdown (and in tests). StoragePartitionImpl* storage_partition() const; void set_storage_partition(StoragePartitionImpl* storage_partition);
diff --git a/content/browser/service_worker/service_worker_process_manager.cc b/content/browser/service_worker/service_worker_process_manager.cc index 738c25b2..54ff396e 100644 --- a/content/browser/service_worker/service_worker_process_manager.cc +++ b/content/browser/service_worker/service_worker_process_manager.cc
@@ -12,6 +12,7 @@ #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/site_instance_impl.h" +#include "content/browser/storage_partition_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/site_instance.h" #include "content/public/common/browser_side_navigation_policy.h" @@ -51,6 +52,7 @@ ServiceWorkerProcessManager::ServiceWorkerProcessManager( BrowserContext* browser_context) : browser_context_(browser_context), + storage_partition_(nullptr), process_id_for_test_(ChildProcessHost::kInvalidUniqueID), new_process_id_for_test_(ChildProcessHost::kInvalidUniqueID), weak_this_factory_(this) { @@ -186,6 +188,8 @@ // In non-PlzNavigate, we must manually track renderer processes in order to // use an existing process. In PlzNavigate, we can depend on SiteInstance to // return an existing process, so just skip this part. + // TODO(clamy): Remove this process reuse mechanism when the non-PlzNavigate + // code path is no longer needed (the feature flag is removed). if (!content::IsBrowserSideNavigationEnabled() && can_use_existing_process) { int process_id = FindAvailableProcess(pattern); if (process_id != ChildProcessHost::kInvalidUniqueID) { @@ -200,14 +204,22 @@ } // ServiceWorkerProcessManager does not know of any renderer processes that - // are available for |pattern|. Create a SiteInstance and ask for a renderer - // process. Attempt to reuse an existing process if possible. - // TODO(clamy): Update the process reuse mechanism above following the - // implementation of - // SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE. + // are available for |pattern|. Create a SiteInstance to ask it for a renderer + // process. Use the site URL from the StoragePartition in case this + // StoragePartition is for guests (e.g., <webview>). + bool use_url_from_storage_partition = + storage_partition_ && + !storage_partition_->site_for_service_worker().is_empty(); scoped_refptr<SiteInstanceImpl> site_instance = - SiteInstanceImpl::CreateForURL(browser_context_, script_url); + SiteInstanceImpl::CreateForURL( + browser_context_, use_url_from_storage_partition + ? storage_partition_->site_for_service_worker() + : script_url); site_instance->set_is_for_service_worker(); + + // Attempt to reuse a renderer process if possible. Note that in the + // <webview> case, process reuse isn't currently supported and a new + // process will always be created (https://crbug.com/752667). DCHECK(site_instance->process_reuse_policy() == SiteInstanceImpl::ProcessReusePolicy::DEFAULT || site_instance->process_reuse_policy() == @@ -217,7 +229,11 @@ SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE); } + // Get the process from the SiteInstance. RenderProcessHost* rph = site_instance->GetProcess(); + DCHECK(!storage_partition_ || + rph->InSameStoragePartition(storage_partition_)); + ServiceWorkerMetrics::StartSituation start_situation; if (!rph->HasConnection()) { // HasConnection() is false means that Init() has not been called or the
diff --git a/content/browser/service_worker/service_worker_process_manager.h b/content/browser/service_worker/service_worker_process_manager.h index 5fb9dd4d..62134aa 100644 --- a/content/browser/service_worker/service_worker_process_manager.h +++ b/content/browser/service_worker/service_worker_process_manager.h
@@ -22,6 +22,7 @@ class BrowserContext; class SiteInstance; +class StoragePartitionImpl; // Interacts with the UI thread to keep RenderProcessHosts alive while the // ServiceWorker system is using them. It also tracks candidate processes @@ -110,6 +111,10 @@ // dereferenced on the UI thread only. base::WeakPtr<ServiceWorkerProcessManager> AsWeakPtr() { return weak_this_; } + void set_storage_partition(StoragePartitionImpl* storage_partition) { + storage_partition_ = storage_partition; + } + private: FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTest, SortProcess); FRIEND_TEST_ALL_PREFIXES(ServiceWorkerProcessManagerTest, @@ -164,8 +169,12 @@ // Protects |browser_context_|. base::Lock browser_context_lock_; + ////////////////////////////////////////////////////////////////////////////// // All fields below are only accessed on the UI thread. + // May be null during initialization and in unit tests. + StoragePartitionImpl* storage_partition_; + // Maps the ID of a running EmbeddedWorkerInstance to information about the // process it's running inside. Since the Instances themselves live on the IO // thread, this can be slightly out of date:
diff --git a/content/browser/service_worker/service_worker_process_manager_unittest.cc b/content/browser/service_worker/service_worker_process_manager_unittest.cc index 52c6326..22c428f0 100644 --- a/content/browser/service_worker/service_worker_process_manager_unittest.cc +++ b/content/browser/service_worker/service_worker_process_manager_unittest.cc
@@ -8,9 +8,12 @@ #include "base/memory/ptr_util.h" #include "base/test/scoped_feature_list.h" #include "content/browser/renderer_host/render_process_host_impl.h" +#include "content/browser/site_instance_impl.h" +#include "content/browser/storage_partition_impl.h" #include "content/common/service_worker/embedded_worker_settings.h" #include "content/public/common/child_process_host.h" #include "content/public/common/content_features.h" +#include "content/public/common/url_constants.h" #include "content/public/test/mock_render_process_host.h" #include "content/public/test/test_browser_context.h" #include "content/public/test/test_browser_thread_bundle.h" @@ -20,6 +23,37 @@ namespace content { +namespace { + +// Keeps track of the most recent |site_instance| passed to +// CreateRenderProcessHost(). +class SiteInstanceRenderProcessHostFactory : public RenderProcessHostFactory { + public: + SiteInstanceRenderProcessHostFactory() = default; + ~SiteInstanceRenderProcessHostFactory() override = default; + + RenderProcessHost* CreateRenderProcessHost( + BrowserContext* browser_context, + SiteInstance* site_instance) const override { + processes_.push_back( + std::make_unique<MockRenderProcessHost>(browser_context)); + last_site_instance_used_ = site_instance; + return processes_.back().get(); + } + + SiteInstance* last_site_instance_used() const { + return last_site_instance_used_; + } + + private: + mutable std::vector<std::unique_ptr<MockRenderProcessHost>> processes_; + mutable SiteInstance* last_site_instance_used_; + + DISALLOW_COPY_AND_ASSIGN(SiteInstanceRenderProcessHostFactory); +}; + +} // namespace + class ServiceWorkerProcessManagerTest : public testing::Test { public: ServiceWorkerProcessManagerTest() {} @@ -30,7 +64,8 @@ new ServiceWorkerProcessManager(browser_context_.get())); pattern_ = GURL("http://www.example.com/"); script_url_ = GURL("http://www.example.com/sw.js"); - render_process_host_factory_.reset(new MockRenderProcessHostFactory()); + render_process_host_factory_.reset( + new SiteInstanceRenderProcessHostFactory()); RenderProcessHostImpl::set_render_process_host_factory( render_process_host_factory_.get()); } @@ -52,9 +87,10 @@ std::unique_ptr<ServiceWorkerProcessManager> process_manager_; GURL pattern_; GURL script_url_; + std::unique_ptr<SiteInstanceRenderProcessHostFactory> + render_process_host_factory_; private: - std::unique_ptr<MockRenderProcessHostFactory> render_process_host_factory_; DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProcessManagerTest); }; @@ -308,4 +344,66 @@ EXPECT_TRUE(process_manager_->instance_info_.empty()); } +// Tests that ServiceWorkerProcessManager uses +// StoragePartitionImpl::site_for_service_worker() when it's set. This enables +// finding the appropriate process when inside a StoragePartition for guests +// (e.g., the <webview> tag). https://crbug.com/781313 +TEST_F(ServiceWorkerProcessManagerTest, + AllocateWorkerProcess_StoragePartitionForGuests) { + const GURL kGuestSiteUrl = + GURL(std::string(content::kGuestScheme).append("://someapp/somepath")); + + // Allocate a process to a worker. It should use |script_url_| as the + // site URL of the SiteInstance. + { + const int kEmbeddedWorkerId = 55; // dummy value + ServiceWorkerProcessManager::AllocatedProcessInfo process_info; + ServiceWorkerStatusCode status = process_manager_->AllocateWorkerProcess( + kEmbeddedWorkerId, pattern_, script_url_, + true /* can_use_existing_process */, &process_info); + EXPECT_EQ(SERVICE_WORKER_OK, status); + // Instead of testing the input to the CreateRenderProcessHost(), it'd be + // more interesting to check the StoragePartition of the returned process + // here and below. Alas, MockRenderProcessHosts always use the default + // StoragePartition. + EXPECT_EQ( + GURL("http://example.com"), + render_process_host_factory_->last_site_instance_used()->GetSiteURL()); + + // Release the process. + process_manager_->ReleaseWorkerProcess(kEmbeddedWorkerId); + } + + // Now change ServiceWorkerProcessManager to use a StoragePartition with + // |site_for_service_worker| set. We must set |site_for_service_worker| + // manually since the production codepath in CreateRenderProcessHost() isn't + // hit here since we are using RenderProcessHostFactory. + scoped_refptr<SiteInstanceImpl> site_instance = + SiteInstanceImpl::CreateForURL(browser_context_.get(), kGuestSiteUrl); + // It'd be more realistic to create a non-default StoragePartition, but there + // would be no added value to this test since MockRenderProcessHost is not + // StoragePartition-aware. + StoragePartitionImpl* storage_partition = static_cast<StoragePartitionImpl*>( + BrowserContext::GetDefaultStoragePartition(browser_context_.get())); + storage_partition->set_site_for_service_worker(site_instance->GetSiteURL()); + process_manager_->set_storage_partition(storage_partition); + + // Allocate a process to a worker. It should use kGuestSiteUrl instead of + // |script_url_| as the site URL of the SiteInstance. + { + const int kEmbeddedWorkerId = 77; // dummy value + ServiceWorkerProcessManager::AllocatedProcessInfo process_info; + ServiceWorkerStatusCode status = process_manager_->AllocateWorkerProcess( + kEmbeddedWorkerId, pattern_, script_url_, + true /* can_use_existing_process */, &process_info); + EXPECT_EQ(SERVICE_WORKER_OK, status); + EXPECT_EQ( + kGuestSiteUrl, + render_process_host_factory_->last_site_instance_used()->GetSiteURL()); + + // Release the process. + process_manager_->ReleaseWorkerProcess(kEmbeddedWorkerId); + } +} + } // namespace content
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index b3ea5f8..684ce2c 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -31,6 +31,7 @@ #include "base/strings/string_split.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/bind_test_util.h" #include "base/test/test_timeouts.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h" @@ -345,6 +346,29 @@ gfx::ToCeiledInt((bounds.y() - root_view->GetViewBounds().y() + 5) * scale_factor)); child_event.click_count = 1; + + // Check the renderer hit-test API return the correct frame for + // the cross site iframe. + base::RunLoop run_loop; + viz::FrameSinkId received_frame_sink_id; + base::Closure quit_closure = + content::GetDeferredQuitTaskForRunLoop(&run_loop); + // TODO(crbug.com/793018): There is a confusion here about scale_factor. + DCHECK_NE(root->current_frame_host()->GetInputTargetClient(), nullptr); + root->current_frame_host()->GetInputTargetClient()->FrameSinkIdAt( + gfx::ScaleToCeiledPoint( + gfx::ToCeiledPoint(child_event.PositionInWidget()), scale_factor, + scale_factor), + base::BindLambdaForTesting([&](const viz::FrameSinkId& id) { + received_frame_sink_id = id; + quit_closure.Run(); + })); + content::RunThisRunLoop(&run_loop); + ASSERT_EQ( + viz::FrameSinkId(root_view->GetRenderWidgetHost()->GetProcess()->GetID(), + rwhv_child->GetRenderWidgetHost()->GetRoutingID()), + received_frame_sink_id); + main_frame_monitor.ResetEventReceived(); child_frame_monitor.ResetEventReceived(); router->RouteMouseEvent(root_view, &child_event, ui::LatencyInfo());
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h index 62ede95f..57aaf22 100644 --- a/content/browser/storage_partition_impl.h +++ b/content/browser/storage_partition_impl.h
@@ -151,6 +151,20 @@ auto& bindings_for_testing() { return bindings_; } + // When this StoragePartition is for guests (e.g., for a <webview> tag), this + // is the site URL to use when creating a SiteInstance for a service worker. + // Typically one would use the script URL of the service worker (e.g., + // "https://example.com/sw.js"), but if this StoragePartition is for guests, + // one must use the "chrome-guest://blahblah" site URL to ensure that the + // service worker stays in this StoragePartition. This is an empty GURL if + // this StoragePartition is not for guests. + void set_site_for_service_worker(const GURL& site_for_service_worker) { + site_for_service_worker_ = site_for_service_worker; + } + const GURL& site_for_service_worker() const { + return site_for_service_worker_; + } + struct DataDeletionHelper; struct QuotaManagedDataDeletionHelper; @@ -298,6 +312,9 @@ // BrowserContext is destroyed, |this| will be destroyed too. BrowserContext* browser_context_; + // See comments for site_for_service_worker(). + GURL site_for_service_worker_; + base::WeakPtrFactory<StoragePartitionImpl> weak_factory_; DISALLOW_COPY_AND_ASSIGN(StoragePartitionImpl);
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index fba08e3..515e457d3 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -285,6 +285,10 @@ void NotifyManifestUrlChanged(const base::Optional<GURL>& manifest_url); + ManifestManagerHost* GetManifestManagerHost() const { + return manifest_manager_host_.get(); + } + #if defined(OS_ANDROID) std::set<RenderWidgetHostImpl*> GetAllRenderWidgetHosts(); void SetImportance(ChildProcessImportance importance);
diff --git a/content/browser/webrtc/webrtc_event_log_manager.cc b/content/browser/webrtc/webrtc_event_log_manager.cc index b91529cc..a5ce88b3 100644 --- a/content/browser/webrtc/webrtc_event_log_manager.cc +++ b/content/browser/webrtc/webrtc_event_log_manager.cc
@@ -4,50 +4,14 @@ #include "content/browser/webrtc/webrtc_event_log_manager.h" -#include <inttypes.h> - -#include <iostream> -#include <limits> - -#include "base/files/file_util.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" #include "base/task_scheduler/post_task.h" #include "content/common/media/peer_connection_tracker_messages.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_process_host.h" -#if defined(OS_WIN) -#define IntToStringType base::IntToString16 -#else -#define IntToStringType base::IntToString -#endif - namespace content { -namespace { -inline void MaybeReplyWithBool(const base::Location& from_here, - base::OnceCallback<void(bool)> reply, - bool value) { - if (reply) { - BrowserThread::PostTask(BrowserThread::UI, from_here, - base::BindOnce(std::move(reply), value)); - } -} - -struct MaybeReplyWithBoolOnExit final { - MaybeReplyWithBoolOnExit(base::OnceCallback<void(bool)> reply, - bool default_value) - : reply(std::move(reply)), value(default_value) {} - ~MaybeReplyWithBoolOnExit() { - if (reply) { - MaybeReplyWithBool(FROM_HERE, std::move(reply), value); - } - } - base::OnceCallback<void(bool)> reply; - bool value; -}; -} // namespace +const size_t kWebRtcEventLogManagerUnlimitedFileSize = 0; base::LazyInstance<WebRtcEventLogManager>::Leaky g_webrtc_event_log_manager = LAZY_INSTANCE_INITIALIZER; @@ -57,10 +21,9 @@ } WebRtcEventLogManager::WebRtcEventLogManager() - : clock_for_testing_(nullptr), - local_logs_observer_(nullptr), - max_local_log_file_size_bytes_(kDefaultMaxLocalLogFileSizeBytes), - file_task_runner_(base::CreateSequencedTaskRunnerWithTraits( + : local_logs_observer_(nullptr), + local_logs_manager_(this), + task_runner_(base::CreateSequencedTaskRunnerWithTraits( {base::MayBlock(), base::TaskPriority::BACKGROUND, base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -75,7 +38,7 @@ int lid, base::OnceCallback<void(bool)> reply) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - file_task_runner_->PostTask( + task_runner_->PostTask( FROM_HERE, base::BindOnce(&WebRtcEventLogManager::PeerConnectionAddedInternal, base::Unretained(this), render_process_id, lid, @@ -87,7 +50,7 @@ int lid, base::OnceCallback<void(bool)> reply) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - file_task_runner_->PostTask( + task_runner_->PostTask( FROM_HERE, base::BindOnce(&WebRtcEventLogManager::PeerConnectionRemovedInternal, base::Unretained(this), render_process_id, lid, @@ -100,7 +63,7 @@ base::OnceCallback<void(bool)> reply) { DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!base_path.empty()); - file_task_runner_->PostTask( + task_runner_->PostTask( FROM_HERE, base::BindOnce(&WebRtcEventLogManager::EnableLocalLoggingInternal, base::Unretained(this), base_path, max_file_size_bytes, @@ -110,7 +73,7 @@ void WebRtcEventLogManager::DisableLocalLogging( base::OnceCallback<void(bool)> reply) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - file_task_runner_->PostTask( + task_runner_->PostTask( FROM_HERE, base::BindOnce(&WebRtcEventLogManager::DisableLocalLoggingInternal, base::Unretained(this), std::move(reply))); @@ -122,312 +85,172 @@ const std::string& output, base::OnceCallback<void(bool)> reply) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - file_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&WebRtcEventLogManager::WriteToLocalLogFile, - base::Unretained(this), render_process_id, lid, - output, std::move(reply))); + task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&WebRtcEventLogManager::OnWebRtcEventLogWriteInternal, + base::Unretained(this), render_process_id, lid, output, + std::move(reply))); } -void WebRtcEventLogManager::SetLocalLogsObserver(LocalLogsObserver* observer, - base::OnceClosure reply) { +void WebRtcEventLogManager::SetLocalLogsObserver( + WebRtcLocalEventLogsObserver* observer, + base::OnceClosure reply) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - file_task_runner_->PostTask( + task_runner_->PostTask( FROM_HERE, base::BindOnce(&WebRtcEventLogManager::SetLocalLogsObserverInternal, base::Unretained(this), observer, std::move(reply))); } +void WebRtcEventLogManager::OnLocalLogStarted(PeerConnectionKey peer_connection, + base::FilePath file_path) { + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + + auto it = peer_connections_with_event_logging_enabled_.find(peer_connection); + if (it != peer_connections_with_event_logging_enabled_.end()) { + // We're already receiving WebRTC event logs for this peer connection. + // Keep track that we also need it for local logging, so that if all + // other reasons (remote logging) stop holding, we still keep it on for + // local logging. + DCHECK_EQ((it->second & LoggingTarget::kLocalLogging), 0u); + it->second |= LoggingTarget::kLocalLogging; + } else { + // This is the first client for WebRTC event logging - let WebRTC know + // that it should start informing us of events. + peer_connections_with_event_logging_enabled_.emplace( + peer_connection, LoggingTarget::kLocalLogging); + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::BindOnce(&WebRtcEventLogManager::UpdateWebRtcEventLoggingState, + base::Unretained(this), peer_connection, true)); + } + + if (local_logs_observer_) { + local_logs_observer_->OnLocalLogStarted(peer_connection, file_path); + } +} + +void WebRtcEventLogManager::OnLocalLogStopped( + PeerConnectionKey peer_connection) { + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + + // Record that we're no longer performing local-logging for this PC. + auto it = peer_connections_with_event_logging_enabled_.find(peer_connection); + CHECK(it != peer_connections_with_event_logging_enabled_.end()); + DCHECK_NE((it->second & LoggingTarget::kLocalLogging), 0u); + it->second &= ~LoggingTarget::kLocalLogging; + + // If we're not doing any other type of logging for this peer connection, + // it's time to stop receiving notifications for it from WebRTC. + if (it->second == 0u) { + peer_connections_with_event_logging_enabled_.erase(it); + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::BindOnce(&WebRtcEventLogManager::UpdateWebRtcEventLoggingState, + base::Unretained(this), peer_connection, false)); + } + + if (local_logs_observer_) { + local_logs_observer_->OnLocalLogStopped(peer_connection); + } +} + void WebRtcEventLogManager::PeerConnectionAddedInternal( int render_process_id, int lid, base::OnceCallback<void(bool)> reply) { - DCHECK(file_task_runner_->RunsTasksInCurrentSequence()); - const auto result = active_peer_connections_.emplace(render_process_id, lid); - - if (!result.second) { // PeerConnection already registered. - MaybeReplyWithBool(FROM_HERE, std::move(reply), false); - return; + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + const bool result = + local_logs_manager_.PeerConnectionAdded(render_process_id, lid); + if (reply) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::BindOnce(std::move(reply), result)); } - - if (!local_logs_base_path_.empty() && - local_logs_.size() < kMaxNumberLocalWebRtcEventLogFiles) { - // Note that success/failure of starting the local log file is unrelated - // to the success/failure of PeerConnectionAdded(). - StartLocalLogFile(render_process_id, lid); - } - - MaybeReplyWithBool(FROM_HERE, std::move(reply), true); } void WebRtcEventLogManager::PeerConnectionRemovedInternal( int render_process_id, int lid, base::OnceCallback<void(bool)> reply) { - DCHECK(file_task_runner_->RunsTasksInCurrentSequence()); - - const PeerConnectionKey key = PeerConnectionKey(render_process_id, lid); - auto peer_connection = active_peer_connections_.find(key); - - if (peer_connection == active_peer_connections_.end()) { - DCHECK(local_logs_.find(key) == local_logs_.end()); - MaybeReplyWithBool(FROM_HERE, std::move(reply), false); - return; + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + const bool result = + local_logs_manager_.PeerConnectionRemoved(render_process_id, lid); + if (reply) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::BindOnce(std::move(reply), result)); } - - auto local_log = local_logs_.find(key); - if (local_log != local_logs_.end()) { - // Note that success/failure of stopping the local log file is unrelated - // to the success/failure of PeerConnectionRemoved(). - StopLocalLogFile(render_process_id, lid); - } - - active_peer_connections_.erase(peer_connection); - - MaybeReplyWithBool(FROM_HERE, std::move(reply), true); } void WebRtcEventLogManager::EnableLocalLoggingInternal( base::FilePath base_path, size_t max_file_size_bytes, base::OnceCallback<void(bool)> reply) { - if (!local_logs_base_path_.empty()) { - MaybeReplyWithBool(FROM_HERE, std::move(reply), false); - return; + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + const bool result = + local_logs_manager_.EnableLogging(base_path, max_file_size_bytes); + if (reply) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::BindOnce(std::move(reply), result)); } - - DCHECK_EQ(local_logs_.size(), 0u); - - local_logs_base_path_ = base_path; - max_local_log_file_size_bytes_ = max_file_size_bytes; - - for (const PeerConnectionKey& peer_connection : active_peer_connections_) { - if (local_logs_.size() >= kMaxNumberLocalWebRtcEventLogFiles) { - break; - } - StartLocalLogFile(peer_connection.render_process_id, peer_connection.lid); - } - - MaybeReplyWithBool(FROM_HERE, std::move(reply), true); } void WebRtcEventLogManager::DisableLocalLoggingInternal( base::OnceCallback<void(bool)> reply) { - if (local_logs_base_path_.empty()) { - MaybeReplyWithBool(FROM_HERE, std::move(reply), false); - return; + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + const bool result = local_logs_manager_.DisableLogging(); + if (reply) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::BindOnce(std::move(reply), result)); } +} - // Perform an orderly closing of all active local logs. - for (auto local_log = local_logs_.begin(); local_log != local_logs_.end();) { - local_log = CloseLocalLogFile(local_log); +void WebRtcEventLogManager::OnWebRtcEventLogWriteInternal( + int render_process_id, + int lid, // Renderer-local PeerConnection ID. + const std::string& output, + base::OnceCallback<void(bool)> reply) { + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + const bool result = + local_logs_manager_.EventLogWrite(render_process_id, lid, output); + if (reply) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::BindOnce(std::move(reply), result)); } - - local_logs_base_path_.clear(); // Marks local-logging as disabled. - max_local_log_file_size_bytes_ = kDefaultMaxLocalLogFileSizeBytes; - - MaybeReplyWithBool(FROM_HERE, std::move(reply), true); } void WebRtcEventLogManager::SetLocalLogsObserverInternal( - LocalLogsObserver* observer, + WebRtcLocalEventLogsObserver* observer, base::OnceClosure reply) { - DCHECK(file_task_runner_->RunsTasksInCurrentSequence()); - + DCHECK(task_runner_->RunsTasksInCurrentSequence()); local_logs_observer_ = observer; - if (reply) { BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, std::move(reply)); } } -void WebRtcEventLogManager::StartLocalLogFile(int render_process_id, int lid) { - DCHECK(file_task_runner_->RunsTasksInCurrentSequence()); - - // Add some information to the name given by the caller. - base::FilePath file_path = - GetLocalFilePath(local_logs_base_path_, render_process_id, lid); - CHECK(!file_path.empty()) << "Couldn't set path for local WebRTC log file."; - - // In the unlikely case that this filename is already taken, find a unique - // number to append to the filename, if possible. - int unique_number = - base::GetUniquePathNumber(file_path, base::FilePath::StringType()); - if (unique_number < 0) { - return; // No available file path was found. - } else if (unique_number != 0) { - // The filename is taken, but a unique number was found. - // TODO(eladalon): Fix the way the unique number is used. - // https://crbug.com/785333 - file_path = file_path.InsertBeforeExtension(FILE_PATH_LITERAL(" (") + - IntToStringType(unique_number) + - FILE_PATH_LITERAL(")")); - } - - // Attempt to create the file. - constexpr int file_flags = base::File::FLAG_CREATE | base::File::FLAG_WRITE | - base::File::FLAG_EXCLUSIVE_WRITE; - base::File file(file_path, file_flags); - if (!file.IsValid() || !file.created()) { - LOG(WARNING) << "Couldn't create and/or open local WebRTC event log file."; - return; - } - - const PeerConnectionKey key(render_process_id, lid); - - // If the file was successfully created, it's now ready to be written to. - DCHECK(local_logs_.find({render_process_id, lid}) == local_logs_.end()); - local_logs_.emplace(key, - LogFile(std::move(file), max_local_log_file_size_bytes_)); - - // The observer needs to be able to run on any TaskQueue. - if (local_logs_observer_) { - local_logs_observer_->OnLocalLogsStarted(key, file_path); - } - - MaybeUpdateWebRtcEventLoggingState(render_process_id, lid); -} - -void WebRtcEventLogManager::StopLocalLogFile(int render_process_id, int lid) { - DCHECK(file_task_runner_->RunsTasksInCurrentSequence()); - auto it = local_logs_.find(PeerConnectionKey(render_process_id, lid)); - if (it == local_logs_.end()) { - return; - } - CloseLocalLogFile(it); - MaybeUpdateWebRtcEventLoggingState(render_process_id, lid); -} - -void WebRtcEventLogManager::WriteToLocalLogFile( - int render_process_id, - int lid, - const std::string& output, - base::OnceCallback<void(bool)> reply) { - DCHECK(file_task_runner_->RunsTasksInCurrentSequence()); - DCHECK_LE(output.length(), - static_cast<size_t>(std::numeric_limits<int>::max())); - - // This object's destructor will ensure a reply (if |reply| is non-empty), - // regardless of which path is taken out of the function. - MaybeReplyWithBoolOnExit on_exit(std::move(reply), false); - - auto it = local_logs_.find(PeerConnectionKey(render_process_id, lid)); - if (it == local_logs_.end()) { - return; - } - - // Observe the file size limit, if any. Note that base::File's interface does - // not allow writing more than numeric_limits<int>::max() bytes at a time. - int output_len = static_cast<int>(output.length()); // DCHECKed above. - LogFile& log_file = it->second; - if (log_file.max_file_size_bytes != kUnlimitedFileSize) { - DCHECK_LT(log_file.file_size_bytes, log_file.max_file_size_bytes); - if (log_file.file_size_bytes + output.length() < log_file.file_size_bytes || - log_file.file_size_bytes + output.length() > - log_file.max_file_size_bytes) { - output_len = log_file.max_file_size_bytes - log_file.file_size_bytes; - } - } - - int written = log_file.file.WriteAtCurrentPos(output.c_str(), output_len); - if (written < 0 || written != output_len) { // Error - LOG(WARNING) << "WebRTC event log output couldn't be written to local " - "file in its entirety."; - CloseLocalLogFile(it); - return; - } - - // Truncated output due to exceeding the maximum is reported as an error - the - // caller is interested to know that not all of its output was written, - // regardless of the reason. - on_exit.value = (static_cast<size_t>(written) == output.length()); - - log_file.file_size_bytes += static_cast<size_t>(written); - if (log_file.max_file_size_bytes != kUnlimitedFileSize) { - DCHECK_LE(log_file.file_size_bytes, log_file.max_file_size_bytes); - if (log_file.file_size_bytes >= log_file.max_file_size_bytes) { - CloseLocalLogFile(it); - } - } -} - -WebRtcEventLogManager::LocalLogFilesMap::iterator -WebRtcEventLogManager::CloseLocalLogFile(LocalLogFilesMap::iterator it) { - DCHECK(file_task_runner_->RunsTasksInCurrentSequence()); - - const PeerConnectionKey peer_connection = it->first; - - it->second.file.Flush(); - it = local_logs_.erase(it); // file.Close() called by destructor. - - if (local_logs_observer_) { - local_logs_observer_->OnLocalLogsStopped(peer_connection); - } - - return it; -} - -void WebRtcEventLogManager::MaybeUpdateWebRtcEventLoggingState( - int render_process_id, - int lid) { - DCHECK(file_task_runner_->RunsTasksInCurrentSequence()); - // Currently we only support local logging, so the state always needs to be - // updated when this function is called. When remote logging will be added, - // we'll need to enable WebRTC logging only when the first of local/remote - // logging is enabled, and disabled when both are disabled. - const PeerConnectionKey key(render_process_id, lid); - const bool enable = (local_logs_.find(key) != local_logs_.end()); - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::BindOnce(&WebRtcEventLogManager::UpdateWebRtcEventLoggingState, - base::Unretained(this), render_process_id, lid, enable)); -} - -void WebRtcEventLogManager::UpdateWebRtcEventLoggingState(int render_process_id, - int lid, - bool enabled) { +void WebRtcEventLogManager::UpdateWebRtcEventLoggingState( + PeerConnectionKey peer_connection, + bool enabled) { + // TODO(eladalon): Add unit tests that would make sure that we really + // instruct WebRTC to start/stop event logs. https://crbug.com/775415 DCHECK_CURRENTLY_ON(BrowserThread::UI); - RenderProcessHost* host = RenderProcessHost::FromID(render_process_id); + RenderProcessHost* host = + RenderProcessHost::FromID(peer_connection.render_process_id); if (!host) { return; // The host has been asynchronously removed; not a problem. } if (enabled) { - host->Send(new PeerConnectionTracker_StartEventLogOutput(lid)); + host->Send( + new PeerConnectionTracker_StartEventLogOutput(peer_connection.lid)); } else { - host->Send(new PeerConnectionTracker_StopEventLog(lid)); + host->Send(new PeerConnectionTracker_StopEventLog(peer_connection.lid)); } } -base::FilePath WebRtcEventLogManager::GetLocalFilePath( - const base::FilePath& base_path, - int render_process_id, - int lid) { - // Expected to be called from within |file_task_runner_|, but there's no - // real constraint for that. - base::Time::Exploded now; - if (clock_for_testing_) { - clock_for_testing_->Now().LocalExplode(&now); - } else { - base::Time::Now().LocalExplode(&now); - } - - // [user_defined]_[date]_[time]_[pid]_[lid].log - char stamp[100]; - int written = - base::snprintf(stamp, arraysize(stamp), "%04d%02d%02d_%02d%02d_%d_%d", - now.year, now.month, now.day_of_month, now.hour, - now.minute, render_process_id, lid); - CHECK_GT(written, 0); - CHECK_LT(static_cast<size_t>(written), arraysize(stamp)); - - return base_path.InsertBeforeExtension(FILE_PATH_LITERAL("_")) - .InsertBeforeExtensionASCII(base::StringPiece(stamp)) - .AddExtension(FILE_PATH_LITERAL("log")); -} - void WebRtcEventLogManager::InjectClockForTesting(base::Clock* clock) { // Testing only; no need for threading guarantees (called before anything // could be put on the TQ). - clock_for_testing_ = clock; + local_logs_manager_.InjectClockForTesting(clock); } } // namespace content
diff --git a/content/browser/webrtc/webrtc_event_log_manager.h b/content/browser/webrtc/webrtc_event_log_manager.h index 2242d1a7..749531d 100644 --- a/content/browser/webrtc/webrtc_event_log_manager.h +++ b/content/browser/webrtc/webrtc_event_log_manager.h
@@ -2,22 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_BROWSER_WEBRTC_WEBRTC_RTC_EVENT_LOG_MANAGER_H_ -#define CONTENT_BROWSER_WEBRTC_WEBRTC_RTC_EVENT_LOG_MANAGER_H_ +#ifndef CONTENT_BROWSER_WEBRTC_WEBRTC_EVENT_LOG_MANAGER_H_ +#define CONTENT_BROWSER_WEBRTC_WEBRTC_EVENT_LOG_MANAGER_H_ #include <map> -#include <set> -#include <string> -#include <tuple> +#include <type_traits> #include "base/callback.h" -#include "base/files/file.h" #include "base/files/file_path.h" #include "base/lazy_instance.h" #include "base/memory/scoped_refptr.h" #include "base/sequenced_task_runner.h" #include "base/time/clock.h" -#include "build/build_config.h" +#include "content/browser/webrtc/webrtc_event_log_manager_common.h" +#include "content/browser/webrtc/webrtc_local_event_log_manager.h" #include "content/common/content_export.h" namespace content { @@ -30,48 +28,9 @@ // TODO(eladalon): This currently only supports the old use-case - locally // stored log files. An upcoming CL will add remote-support. // https://crbug.com/775415 -class CONTENT_EXPORT WebRtcEventLogManager { +class CONTENT_EXPORT WebRtcEventLogManager + : protected WebRtcLocalEventLogsObserver { public: - // For a given Chrome session, this is a unique key for PeerConnections. - // It's not, however, unique between sessions (after Chrome is restarted). - struct PeerConnectionKey { - constexpr PeerConnectionKey(int render_process_id, int lid) - : render_process_id(render_process_id), lid(lid) {} - - bool operator==(const PeerConnectionKey& other) const { - return std::tie(render_process_id, lid) == - std::tie(other.render_process_id, other.lid); - } - - bool operator<(const PeerConnectionKey& other) const { - return std::tie(render_process_id, lid) < - std::tie(other.render_process_id, other.lid); - } - - int render_process_id; - int lid; // Renderer-local PeerConnection ID. - }; - - // Allow an observer to be registered for notifications of local log files - // being started/stopped, and the paths which will be used for these logs. - class LocalLogsObserver { - public: - virtual ~LocalLogsObserver() = default; - virtual void OnLocalLogsStarted(PeerConnectionKey peer_connection, - base::FilePath file_path) = 0; - virtual void OnLocalLogsStopped(PeerConnectionKey peer_connection) = 0; - }; - - static constexpr size_t kUnlimitedFileSize = 0; - -#if defined(OS_ANDROID) - static const size_t kMaxNumberLocalWebRtcEventLogFiles = 3; - static const size_t kDefaultMaxLocalLogFileSizeBytes = 10000000; -#else - static const size_t kMaxNumberLocalWebRtcEventLogFiles = 5; - static const size_t kDefaultMaxLocalLogFileSizeBytes = 60000000; -#endif - static WebRtcEventLogManager* GetInstance(); // Currently, we only support manual logs initiated by the user @@ -146,32 +105,36 @@ // the observer post them there. // If a reply callback is given, it will be posted back to BrowserThread::UI // after the observer has been set. - void SetLocalLogsObserver(LocalLogsObserver* observer, + void SetLocalLogsObserver(WebRtcLocalEventLogsObserver* observer, base::OnceClosure reply = base::OnceClosure()); protected: - friend class WebRtcEventLogManagerTest; // unit tests inject a frozen clock. + friend class WebRtcEventLogManagerTest; // Unit tests inject a frozen clock. friend struct base::LazyInstanceTraitsBase<WebRtcEventLogManager>; - struct LogFile { - LogFile(base::File file, size_t max_file_size_bytes) - : file(std::move(file)), - max_file_size_bytes(max_file_size_bytes), - file_size_bytes(0) {} - base::File file; - const size_t max_file_size_bytes; - size_t file_size_bytes; - }; - - typedef std::map<PeerConnectionKey, LogFile> LocalLogFilesMap; - WebRtcEventLogManager(); - virtual ~WebRtcEventLogManager(); + ~WebRtcEventLogManager() override; + + private: + using PeerConnectionKey = WebRtcEventLogPeerConnectionKey; + + // This bitmap allows us to track for which clients (local/remote logging) + // we have turned WebRTC event logging on for a given peer connection, so that + // we may turn it off only when the last client no longer needs it. + enum LoggingTarget : unsigned int { + kLocalLogging = 0x01 + // TODO(eladalon): Add kRemoteLogging as 0x02. https://crbug.com/775415 + }; + using LoggingTargetBitmap = std::underlying_type<LoggingTarget>::type; + + // WebRtcLocalEventLogsObserver implementation: + void OnLocalLogStarted(PeerConnectionKey peer_connection, + base::FilePath file_path) override; + void OnLocalLogStopped(PeerConnectionKey peer_connection) override; void PeerConnectionAddedInternal(int render_process_id, int lid, base::OnceCallback<void(bool)> reply); - void PeerConnectionRemovedInternal(int render_process_id, int lid, base::OnceCallback<void(bool)> reply); @@ -179,78 +142,45 @@ void EnableLocalLoggingInternal(base::FilePath base_path, size_t max_file_size_bytes, base::OnceCallback<void(bool)> reply); - void DisableLocalLoggingInternal(base::OnceCallback<void(bool)> reply); - void SetLocalLogsObserverInternal(LocalLogsObserver* observer, + void OnWebRtcEventLogWriteInternal( + int render_process_id, + int lid, // Renderer-local PeerConnection ID. + const std::string& output, + base::OnceCallback<void(bool)> reply); + + void SetLocalLogsObserverInternal(WebRtcLocalEventLogsObserver* observer, base::OnceClosure reply); - // Local log file handling. - void StartLocalLogFile(int render_process_id, int lid); - void StopLocalLogFile(int render_process_id, int lid); - void WriteToLocalLogFile(int render_process_id, - int lid, - const std::string& output, - base::OnceCallback<void(bool)> reply); - LocalLogFilesMap::iterator CloseLocalLogFile(LocalLogFilesMap::iterator it); - - // Determine whether WebRTC state needs to be updated for the given peer - // connection, and if so, sends a message back to the UI process to do so. - void MaybeUpdateWebRtcEventLoggingState(int render_process_id, int lid); - - // Determine whether WebRTC state needs to be updated for the given peer - // connection, and if so, sends a message back to the UI process to do so. - void UpdateWebRtcEventLoggingState(int render_process_id, - int lid, + // Send a message to WebRTC telling it to start/stop sending event-log + // notifications for a given peer connection. + void UpdateWebRtcEventLoggingState(PeerConnectionKey peer_connection, bool enabled); - // Derives the name of a local log file. The format is: - // [user_defined]_[date]_[time]_[pid]_[lid].log - base::FilePath GetLocalFilePath(const base::FilePath& base_path, - int render_process_id, - int lid); - - // Only used for testing, so we have no threading concenrs here; it should - // always be called before anything that might post to the internal TQ. void InjectClockForTesting(base::Clock* clock); - // For unit tests only, and specifically for unit tests that verify the - // filename format (derived from the current time as well as the renderer PID - // and PeerConnection local ID), we want to make sure that the time and date - // cannot change between the time the clock is read by the unit under test - // (namely WebRtcEventLogManager) and the time it's read by the test. - base::Clock* clock_for_testing_; - - // Currently active peer connections. PeerConnections which have been closed - // are not considered active, regardless of whether they have been torn down. - std::set<PeerConnectionKey> active_peer_connections_; - - // Local log files, stored at the behest of the user (via WebRTCInternals). - // TODO(eladalon): Add an additional container with logs that will be uploaded - // to the server. https://crbug.com/775415 - LocalLogFilesMap local_logs_; - // Observer which will be informed whenever a local log file is started or - // stopped. Its callbacks are called synchronously from |file_task_runner_|, + // stopped. Its callbacks are called synchronously from |task_runner_|, // so the observer needs to be able to either run from any (sequenced) runner. - LocalLogsObserver* local_logs_observer_; + WebRtcLocalEventLogsObserver* local_logs_observer_; - // If FilePath is empty, local logging is disabled. - // If nonempty, local logging is enabled, and all local logs will be saved - // to this directory. - base::FilePath local_logs_base_path_; + // Manages local-bound logs - logs stored on the local filesystem when + // logging has been explicitly enabled by the user. + WebRtcLocalEventLogManager local_logs_manager_; - // The maximum size for local logs, in bytes. Note that kUnlimitedFileSize is - // a sentinel value (with a self-explanatory name). - size_t max_local_log_file_size_bytes_; + // This keeps track of which peer connections have event logging turned on + // in WebRTC, and for which client(s). + std::map<PeerConnectionKey, LoggingTargetBitmap> + peer_connections_with_event_logging_enabled_; - // File operations will run sequentially on this runner. - scoped_refptr<base::SequencedTaskRunner> file_task_runner_; + // The main logic will run sequentially on this runner, on which blocking + // tasks are allowed. + scoped_refptr<base::SequencedTaskRunner> task_runner_; - private: DISALLOW_COPY_AND_ASSIGN(WebRtcEventLogManager); }; } // namespace content -#endif // CONTENT_BROWSER_WEBRTC_WEBRTC_RTC_EVENT_LOG_MANAGER_H_ +#endif // CONTENT_BROWSER_WEBRTC_WEBRTC_EVENT_LOG_MANAGER_H_
diff --git a/content/browser/webrtc/webrtc_event_log_manager_common.h b/content/browser/webrtc/webrtc_event_log_manager_common.h new file mode 100644 index 0000000..17ed338 --- /dev/null +++ b/content/browser/webrtc/webrtc_event_log_manager_common.h
@@ -0,0 +1,53 @@ +// Copyright (c) 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_WEBRTC_WEBRTC_RTC_EVENT_LOG_MANAGER_COMMON_H_ +#define CONTENT_BROWSER_WEBRTC_WEBRTC_RTC_EVENT_LOG_MANAGER_COMMON_H_ + +#include <tuple> + +#include "base/files/file_path.h" +#include "build/build_config.h" +#include "content/common/content_export.h" + +namespace content { + +CONTENT_EXPORT extern const size_t kWebRtcEventLogManagerUnlimitedFileSize; + +CONTENT_EXPORT extern const size_t kDefaultMaxLocalLogFileSizeBytes; +CONTENT_EXPORT extern const size_t kMaxNumberLocalWebRtcEventLogFiles; + +// For a given Chrome session, this is a unique key for PeerConnections. +// It's not, however, unique between sessions (after Chrome is restarted). +struct WebRtcEventLogPeerConnectionKey { + constexpr WebRtcEventLogPeerConnectionKey(int render_process_id, int lid) + : render_process_id(render_process_id), lid(lid) {} + + bool operator==(const WebRtcEventLogPeerConnectionKey& other) const { + return std::tie(render_process_id, lid) == + std::tie(other.render_process_id, other.lid); + } + + bool operator<(const WebRtcEventLogPeerConnectionKey& other) const { + return std::tie(render_process_id, lid) < + std::tie(other.render_process_id, other.lid); + } + + int render_process_id; + int lid; // Renderer-local PeerConnection ID. +}; + +// An observer for notifications of local log files being started/stopped, and +// the paths which will be used for these logs. +class WebRtcLocalEventLogsObserver { + public: + virtual ~WebRtcLocalEventLogsObserver() = default; + virtual void OnLocalLogStarted(WebRtcEventLogPeerConnectionKey pc_key, + base::FilePath file_path) = 0; + virtual void OnLocalLogStopped(WebRtcEventLogPeerConnectionKey pc_key) = 0; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_WEBRTC_WEBRTC_RTC_EVENT_LOG_MANAGER_COMMON_H_
diff --git a/content/browser/webrtc/webrtc_event_log_manager_unittest.cc b/content/browser/webrtc/webrtc_event_log_manager_unittest.cc index 9acc88a..068361f 100644 --- a/content/browser/webrtc/webrtc_event_log_manager_unittest.cc +++ b/content/browser/webrtc/webrtc_event_log_manager_unittest.cc
@@ -38,15 +38,16 @@ using ::testing::Invoke; using ::testing::NiceMock; using ::testing::StrictMock; -using PeerConnectionKey = WebRtcEventLogManager::PeerConnectionKey; + +using PeerConnectionKey = WebRtcEventLogPeerConnectionKey; namespace { -class MockLocalLogsObserver : public WebRtcEventLogManager::LocalLogsObserver { +class MockWebRtcLocalEventLogsObserver : public WebRtcLocalEventLogsObserver { public: - ~MockLocalLogsObserver() override = default; - MOCK_METHOD2(OnLocalLogsStarted, void(PeerConnectionKey, base::FilePath)); - MOCK_METHOD1(OnLocalLogsStopped, void(PeerConnectionKey)); + ~MockWebRtcLocalEventLogsObserver() override = default; + MOCK_METHOD2(OnLocalLogStarted, void(PeerConnectionKey, base::FilePath)); + MOCK_METHOD1(OnLocalLogStopped, void(PeerConnectionKey)); }; auto SaveKeyAndFilePathTo(base::Optional<PeerConnectionKey>* key_output, @@ -128,13 +129,13 @@ } bool EnableLocalLogging( - size_t max_size_bytes = WebRtcEventLogManager::kUnlimitedFileSize) { + size_t max_size_bytes = kWebRtcEventLogManagerUnlimitedFileSize) { return EnableLocalLogging(base_path_, max_size_bytes); } bool EnableLocalLogging( base::FilePath base_path, - size_t max_size_bytes = WebRtcEventLogManager::kUnlimitedFileSize) { + size_t max_size_bytes = kWebRtcEventLogManagerUnlimitedFileSize) { bool result; manager_->EnableLocalLogging(base_path, max_size_bytes, BoolReplyClosure(&result)); @@ -149,8 +150,7 @@ return result; } - void SetLocalLogsObserver( - WebRtcEventLogManager::LocalLogsObserver* observer) { + void SetLocalLogsObserver(WebRtcLocalEventLogsObserver* observer) { manager_->SetLocalLogsObserver(observer, VoidReplyClosure()); WaitForReply(); } @@ -268,39 +268,39 @@ } TEST_F(WebRtcEventLogManagerTest, - OnLocalLogsStartedNotCalledIfLocalLoggingEnabledWithoutPeerConnections) { - MockLocalLogsObserver observer; - EXPECT_CALL(observer, OnLocalLogsStarted(_, _)).Times(0); - EXPECT_CALL(observer, OnLocalLogsStopped(_)).Times(0); + OnLocalLogStartedNotCalledIfLocalLoggingEnabledWithoutPeerConnections) { + MockWebRtcLocalEventLogsObserver observer; + EXPECT_CALL(observer, OnLocalLogStarted(_, _)).Times(0); + EXPECT_CALL(observer, OnLocalLogStopped(_)).Times(0); SetLocalLogsObserver(&observer); ASSERT_TRUE(EnableLocalLogging()); } TEST_F(WebRtcEventLogManagerTest, - OnLocalLogsStartedCalledForPeerConnectionAddedAndLocalLoggingEnabled) { - MockLocalLogsObserver observer; + OnLocalLogStartedCalledForPeerConnectionAddedAndLocalLoggingEnabled) { + MockWebRtcLocalEventLogsObserver observer; PeerConnectionKey peer_connection(kRenderProcessId, kPeerConnectionId); - EXPECT_CALL(observer, OnLocalLogsStarted(peer_connection, _)).Times(1); + EXPECT_CALL(observer, OnLocalLogStarted(peer_connection, _)).Times(1); SetLocalLogsObserver(&observer); ASSERT_TRUE(PeerConnectionAdded(kRenderProcessId, kPeerConnectionId)); ASSERT_TRUE(EnableLocalLogging()); } TEST_F(WebRtcEventLogManagerTest, - OnLocalLogsStartedCalledForLocalLoggingEnabledAndPeerConnectionAdded) { - MockLocalLogsObserver observer; + OnLocalLogStartedCalledForLocalLoggingEnabledAndPeerConnectionAdded) { + MockWebRtcLocalEventLogsObserver observer; PeerConnectionKey peer_connection(kRenderProcessId, kPeerConnectionId); - EXPECT_CALL(observer, OnLocalLogsStarted(peer_connection, _)).Times(1); + EXPECT_CALL(observer, OnLocalLogStarted(peer_connection, _)).Times(1); SetLocalLogsObserver(&observer); ASSERT_TRUE(EnableLocalLogging()); ASSERT_TRUE(PeerConnectionAdded(kRenderProcessId, kPeerConnectionId)); } TEST_F(WebRtcEventLogManagerTest, - OnLocalLogsStoppedCalledAfterLocalLoggingDisabled) { - NiceMock<MockLocalLogsObserver> observer; + OnLocalLogStoppedCalledAfterLocalLoggingDisabled) { + NiceMock<MockWebRtcLocalEventLogsObserver> observer; PeerConnectionKey peer_connection(kRenderProcessId, kPeerConnectionId); - EXPECT_CALL(observer, OnLocalLogsStopped(peer_connection)).Times(1); + EXPECT_CALL(observer, OnLocalLogStopped(peer_connection)).Times(1); SetLocalLogsObserver(&observer); ASSERT_TRUE(PeerConnectionAdded(kRenderProcessId, kPeerConnectionId)); ASSERT_TRUE(EnableLocalLogging()); @@ -308,10 +308,10 @@ } TEST_F(WebRtcEventLogManagerTest, - OnLocalLogsStoppedCalledAfterPeerConnectionRemoved) { - NiceMock<MockLocalLogsObserver> observer; + OnLocalLogStoppedCalledAfterPeerConnectionRemoved) { + NiceMock<MockWebRtcLocalEventLogsObserver> observer; PeerConnectionKey peer_connection(kRenderProcessId, kPeerConnectionId); - EXPECT_CALL(observer, OnLocalLogsStopped(peer_connection)).Times(1); + EXPECT_CALL(observer, OnLocalLogStopped(peer_connection)).Times(1); SetLocalLogsObserver(&observer); ASSERT_TRUE(PeerConnectionAdded(kRenderProcessId, kPeerConnectionId)); ASSERT_TRUE(EnableLocalLogging()); @@ -319,9 +319,9 @@ } TEST_F(WebRtcEventLogManagerTest, RemovedLocalLogsObserverReceivesNoCalls) { - StrictMock<MockLocalLogsObserver> observer; - EXPECT_CALL(observer, OnLocalLogsStarted(_, _)).Times(0); - EXPECT_CALL(observer, OnLocalLogsStopped(_)).Times(0); + StrictMock<MockWebRtcLocalEventLogsObserver> observer; + EXPECT_CALL(observer, OnLocalLogStarted(_, _)).Times(0); + EXPECT_CALL(observer, OnLocalLogStopped(_)).Times(0); SetLocalLogsObserver(&observer); SetLocalLogsObserver(nullptr); ASSERT_TRUE(EnableLocalLogging()); @@ -330,12 +330,12 @@ } TEST_F(WebRtcEventLogManagerTest, LocalLogCreatesEmptyFileWhenStarted) { - NiceMock<MockLocalLogsObserver> observer; + NiceMock<MockWebRtcLocalEventLogsObserver> observer; SetLocalLogsObserver(&observer); base::Optional<PeerConnectionKey> key; base::Optional<base::FilePath> file_path; - ON_CALL(observer, OnLocalLogsStarted(_, _)) + ON_CALL(observer, OnLocalLogStarted(_, _)) .WillByDefault(Invoke(SaveKeyAndFilePathTo(&key, &file_path))); ASSERT_TRUE(EnableLocalLogging()); @@ -354,12 +354,12 @@ } TEST_F(WebRtcEventLogManagerTest, LocalLogCreateAndWriteToFile) { - NiceMock<MockLocalLogsObserver> observer; + NiceMock<MockWebRtcLocalEventLogsObserver> observer; SetLocalLogsObserver(&observer); base::Optional<PeerConnectionKey> key; base::Optional<base::FilePath> file_path; - ON_CALL(observer, OnLocalLogsStarted(_, _)) + ON_CALL(observer, OnLocalLogStarted(_, _)) .WillByDefault(Invoke(SaveKeyAndFilePathTo(&key, &file_path))); ASSERT_TRUE(EnableLocalLogging()); @@ -381,12 +381,12 @@ } TEST_F(WebRtcEventLogManagerTest, LocalLogMultipleWritesToSameFile) { - NiceMock<MockLocalLogsObserver> observer; + NiceMock<MockWebRtcLocalEventLogsObserver> observer; SetLocalLogsObserver(&observer); base::Optional<PeerConnectionKey> key; base::Optional<base::FilePath> file_path; - ON_CALL(observer, OnLocalLogsStarted(_, _)) + ON_CALL(observer, OnLocalLogStarted(_, _)) .WillByDefault(Invoke(SaveKeyAndFilePathTo(&key, &file_path))); ASSERT_TRUE(EnableLocalLogging()); @@ -415,12 +415,12 @@ } TEST_F(WebRtcEventLogManagerTest, LocalLogFileSizeLimitNotExceeded) { - NiceMock<MockLocalLogsObserver> observer; + NiceMock<MockWebRtcLocalEventLogsObserver> observer; SetLocalLogsObserver(&observer); base::Optional<PeerConnectionKey> key; base::Optional<base::FilePath> file_path; - ON_CALL(observer, OnLocalLogsStarted(_, _)) + ON_CALL(observer, OnLocalLogStarted(_, _)) .WillByDefault(Invoke(SaveKeyAndFilePathTo(&key, &file_path))); const std::string log = "There lies the port; the vessel puffs her sail:"; @@ -436,7 +436,7 @@ // A failure is reported, because not everything could be written. The file // will also be closed. const auto pc = PeerConnectionKey(kRenderProcessId, kPeerConnectionId); - EXPECT_CALL(observer, OnLocalLogsStopped(pc)).Times(1); + EXPECT_CALL(observer, OnLocalLogStopped(pc)).Times(1); ASSERT_FALSE(OnWebRtcEventLogWrite(kRenderProcessId, kPeerConnectionId, log)); // Additional calls to Write() have no effect. @@ -449,15 +449,15 @@ } TEST_F(WebRtcEventLogManagerTest, LocalLogSanityOverUnlimitedFileSizes) { - NiceMock<MockLocalLogsObserver> observer; + NiceMock<MockWebRtcLocalEventLogsObserver> observer; SetLocalLogsObserver(&observer); base::Optional<PeerConnectionKey> key; base::Optional<base::FilePath> file_path; - ON_CALL(observer, OnLocalLogsStarted(_, _)) + ON_CALL(observer, OnLocalLogStarted(_, _)) .WillByDefault(Invoke(SaveKeyAndFilePathTo(&key, &file_path))); - ASSERT_TRUE(EnableLocalLogging(WebRtcEventLogManager::kUnlimitedFileSize)); + ASSERT_TRUE(EnableLocalLogging(kWebRtcEventLogManagerUnlimitedFileSize)); ASSERT_TRUE(PeerConnectionAdded(kRenderProcessId, kPeerConnectionId)); ASSERT_TRUE(key); ASSERT_EQ(*key, PeerConnectionKey(kRenderProcessId, kPeerConnectionId)); @@ -478,12 +478,12 @@ } TEST_F(WebRtcEventLogManagerTest, LocalLogNoWriteAfterLogStopped) { - NiceMock<MockLocalLogsObserver> observer; + NiceMock<MockWebRtcLocalEventLogsObserver> observer; SetLocalLogsObserver(&observer); base::Optional<PeerConnectionKey> key; base::Optional<base::FilePath> file_path; - ON_CALL(observer, OnLocalLogsStarted(_, _)) + ON_CALL(observer, OnLocalLogStarted(_, _)) .WillByDefault(Invoke(SaveKeyAndFilePathTo(&key, &file_path))); ASSERT_TRUE(EnableLocalLogging()); @@ -497,7 +497,7 @@ ASSERT_TRUE( OnWebRtcEventLogWrite(kRenderProcessId, kPeerConnectionId, log_before)); const auto pc = PeerConnectionKey(kRenderProcessId, kPeerConnectionId); - EXPECT_CALL(observer, OnLocalLogsStopped(pc)).Times(1); + EXPECT_CALL(observer, OnLocalLogStopped(pc)).Times(1); ASSERT_TRUE(PeerConnectionRemoved(kRenderProcessId, kPeerConnectionId)); const std::string log_after = "log_after_stop"; @@ -510,11 +510,11 @@ } TEST_F(WebRtcEventLogManagerTest, LocalLogOnlyWritesTheLogsAfterStarted) { - NiceMock<MockLocalLogsObserver> observer; + NiceMock<MockWebRtcLocalEventLogsObserver> observer; SetLocalLogsObserver(&observer); // Calls to Write() before the log was started are ignored. - EXPECT_CALL(observer, OnLocalLogsStarted(_, _)).Times(0); + EXPECT_CALL(observer, OnLocalLogStarted(_, _)).Times(0); const std::string log1 = "The lights begin to twinkle from the rocks:"; ASSERT_FALSE( OnWebRtcEventLogWrite(kRenderProcessId, kPeerConnectionId, log1)); @@ -522,7 +522,7 @@ base::Optional<PeerConnectionKey> key; base::Optional<base::FilePath> file_path; - EXPECT_CALL(observer, OnLocalLogsStarted(_, _)) + EXPECT_CALL(observer, OnLocalLogStarted(_, _)) .Times(1) .WillOnce(Invoke(SaveKeyAndFilePathTo(&key, &file_path))); @@ -549,7 +549,7 @@ // Note: This test also covers the scenario LocalLogExistingFilesNotOverwritten, // which is therefore not explicitly tested. TEST_F(WebRtcEventLogManagerTest, LocalLoggingRestartCreatesNewFile) { - NiceMock<MockLocalLogsObserver> observer; + NiceMock<MockWebRtcLocalEventLogsObserver> observer; SetLocalLogsObserver(&observer); const std::vector<std::string> logs = {"<setup>", "<punchline>", "<encore>"}; @@ -559,7 +559,7 @@ ASSERT_TRUE(PeerConnectionAdded(kRenderProcessId, kPeerConnectionId)); for (size_t i = 0; i < logs.size(); i++) { - ON_CALL(observer, OnLocalLogsStarted(_, _)) + ON_CALL(observer, OnLocalLogStarted(_, _)) .WillByDefault(Invoke(SaveKeyAndFilePathTo(&keys[i], &file_paths[i]))); ASSERT_TRUE(EnableLocalLogging()); ASSERT_TRUE(keys[i]); @@ -579,7 +579,7 @@ } TEST_F(WebRtcEventLogManagerTest, LocalLogMultipleActiveFiles) { - NiceMock<MockLocalLogsObserver> observer; + NiceMock<MockWebRtcLocalEventLogsObserver> observer; SetLocalLogsObserver(&observer); ASSERT_TRUE(EnableLocalLogging()); @@ -592,7 +592,7 @@ for (size_t i = 0; i < keys.size(); i++) { base::Optional<PeerConnectionKey> key; - ON_CALL(observer, OnLocalLogsStarted(_, _)) + ON_CALL(observer, OnLocalLogStarted(_, _)) .WillByDefault(Invoke(SaveKeyAndFilePathTo(&key, &file_paths[i]))); ASSERT_TRUE(PeerConnectionAdded(keys[i]->render_process_id, keys[i]->lid)); ASSERT_TRUE(key); @@ -620,45 +620,44 @@ } TEST_F(WebRtcEventLogManagerTest, LocalLogLimitActiveLocalLogFiles) { - NiceMock<MockLocalLogsObserver> observer; + NiceMock<MockWebRtcLocalEventLogsObserver> observer; SetLocalLogsObserver(&observer); ASSERT_TRUE(EnableLocalLogging()); - const int kMaxLocalLogFiles = static_cast<int>( - WebRtcEventLogManager::kMaxNumberLocalWebRtcEventLogFiles); + const int kMaxLocalLogFiles = + static_cast<int>(kMaxNumberLocalWebRtcEventLogFiles); int i; for (i = 0; i < kMaxLocalLogFiles; i++) { - EXPECT_CALL(observer, OnLocalLogsStarted(PeerConnectionKey(i, i), _)) + EXPECT_CALL(observer, OnLocalLogStarted(PeerConnectionKey(i, i), _)) .Times(1); ASSERT_TRUE(PeerConnectionAdded(i, i)); } - EXPECT_CALL(observer, OnLocalLogsStarted(_, _)).Times(0); + EXPECT_CALL(observer, OnLocalLogStarted(_, _)).Times(0); ASSERT_TRUE(PeerConnectionAdded(i, i)); } // When a log reaches its maximum size limit, it is closed, and no longer // counted towards the limit. TEST_F(WebRtcEventLogManagerTest, LocalLogFilledLogNotCountedTowardsFileLimit) { - NiceMock<MockLocalLogsObserver> observer; + NiceMock<MockWebRtcLocalEventLogsObserver> observer; SetLocalLogsObserver(&observer); const std::string log = "very_short_log"; ASSERT_TRUE(EnableLocalLogging(log.size())); - const int kMaxLocalLogFiles = static_cast<int>( - WebRtcEventLogManager::kMaxNumberLocalWebRtcEventLogFiles); + const int kMaxLocalLogFiles = + static_cast<int>(kMaxNumberLocalWebRtcEventLogFiles); int i; for (i = 0; i < kMaxLocalLogFiles - 1; i++) { - EXPECT_CALL(observer, OnLocalLogsStarted(PeerConnectionKey(i, i), _)) + EXPECT_CALL(observer, OnLocalLogStarted(PeerConnectionKey(i, i), _)) .Times(1); ASSERT_TRUE(PeerConnectionAdded(i, i)); } // Last allowed log (we've started kMaxLocalLogFiles - 1 so far). - EXPECT_CALL(observer, OnLocalLogsStarted(PeerConnectionKey(i, i), _)) - .Times(1); + EXPECT_CALL(observer, OnLocalLogStarted(PeerConnectionKey(i, i), _)).Times(1); ASSERT_TRUE(PeerConnectionAdded(i, i)); // By writing to it, we fill it and end up closing it, allowing an additional // log to be written. @@ -666,40 +665,37 @@ // We now have room for one additional log. ++i; - EXPECT_CALL(observer, OnLocalLogsStarted(PeerConnectionKey(i, i), _)) - .Times(1); + EXPECT_CALL(observer, OnLocalLogStarted(PeerConnectionKey(i, i), _)).Times(1); ASSERT_TRUE(PeerConnectionAdded(i, i)); } TEST_F(WebRtcEventLogManagerTest, LocalLogForRemovedPeerConnectionFilledLogNotCountedTowardsFileLimit) { - NiceMock<MockLocalLogsObserver> observer; + NiceMock<MockWebRtcLocalEventLogsObserver> observer; SetLocalLogsObserver(&observer); ASSERT_TRUE(EnableLocalLogging()); - const int kMaxLocalLogFiles = static_cast<int>( - WebRtcEventLogManager::kMaxNumberLocalWebRtcEventLogFiles); + const int kMaxLocalLogFiles = + static_cast<int>(kMaxNumberLocalWebRtcEventLogFiles); int i; for (i = 0; i < kMaxLocalLogFiles - 1; i++) { - EXPECT_CALL(observer, OnLocalLogsStarted(PeerConnectionKey(i, i), _)) + EXPECT_CALL(observer, OnLocalLogStarted(PeerConnectionKey(i, i), _)) .Times(1); ASSERT_TRUE(PeerConnectionAdded(i, i)); } // Last allowed log (we've started kMaxLocalLogFiles - 1 so far). - EXPECT_CALL(observer, OnLocalLogsStarted(PeerConnectionKey(i, i), _)) - .Times(1); + EXPECT_CALL(observer, OnLocalLogStarted(PeerConnectionKey(i, i), _)).Times(1); ASSERT_TRUE(PeerConnectionAdded(i, i)); // By removing this peer connection, we allowi an additional log. - EXPECT_CALL(observer, OnLocalLogsStopped(PeerConnectionKey(i, i))).Times(1); + EXPECT_CALL(observer, OnLocalLogStopped(PeerConnectionKey(i, i))).Times(1); ASSERT_TRUE(PeerConnectionRemoved(i, i)); // We now have room for one additional log. ++i; - EXPECT_CALL(observer, OnLocalLogsStarted(PeerConnectionKey(i, i), _)) - .Times(1); + EXPECT_CALL(observer, OnLocalLogStarted(PeerConnectionKey(i, i), _)).Times(1); ASSERT_TRUE(PeerConnectionAdded(i, i)); } @@ -713,12 +709,12 @@ } TEST_F(WebRtcEventLogManagerTest, LocalLogIllegalPath) { - StrictMock<MockLocalLogsObserver> observer; + StrictMock<MockWebRtcLocalEventLogsObserver> observer; SetLocalLogsObserver(&observer); // Since the log file won't be properly opened, these will not be called. - EXPECT_CALL(observer, OnLocalLogsStarted(_, _)).Times(0); - EXPECT_CALL(observer, OnLocalLogsStopped(_)).Times(0); + EXPECT_CALL(observer, OnLocalLogStarted(_, _)).Times(0); + EXPECT_CALL(observer, OnLocalLogStopped(_)).Times(0); ASSERT_TRUE(PeerConnectionAdded(kRenderProcessId, kPeerConnectionId)); @@ -741,12 +737,12 @@ permissions &= ~write_permissions; ASSERT_TRUE(base::SetPosixFilePermissions(base_dir_, permissions)); - StrictMock<MockLocalLogsObserver> observer; + StrictMock<MockWebRtcLocalEventLogsObserver> observer; SetLocalLogsObserver(&observer); // Since the log file won't be properly opened, these will not be called. - EXPECT_CALL(observer, OnLocalLogsStarted(_, _)).Times(0); - EXPECT_CALL(observer, OnLocalLogsStopped(_)).Times(0); + EXPECT_CALL(observer, OnLocalLogStarted(_, _)).Times(0); + EXPECT_CALL(observer, OnLocalLogStopped(_)).Times(0); ASSERT_TRUE(PeerConnectionAdded(kRenderProcessId, kPeerConnectionId)); @@ -769,7 +765,7 @@ #endif // defined(OS_POSIX) && !defined(OS_FUCHSIA) TEST_F(WebRtcEventLogManagerTest, LocalLogEmptyStringHandledGracefully) { - NiceMock<MockLocalLogsObserver> observer; + NiceMock<MockWebRtcLocalEventLogsObserver> observer; SetLocalLogsObserver(&observer); // By writing a log after the empty string, we show that no odd behavior is @@ -781,7 +777,7 @@ ASSERT_TRUE(PeerConnectionAdded(kRenderProcessId, kPeerConnectionId)); for (size_t i = 0; i < logs.size(); i++) { - ON_CALL(observer, OnLocalLogsStarted(_, _)) + ON_CALL(observer, OnLocalLogStarted(_, _)) .WillByDefault(Invoke(SaveKeyAndFilePathTo(&keys[i], &file_paths[i]))); ASSERT_TRUE(EnableLocalLogging()); ASSERT_TRUE(keys[i]); @@ -803,12 +799,12 @@ // The logs would typically be binary. However, the other tests only cover ASCII // characters, for readability. This test shows that this is not a problem. TEST_F(WebRtcEventLogManagerTest, LocalLogAllPossibleCharacters) { - NiceMock<MockLocalLogsObserver> observer; + NiceMock<MockWebRtcLocalEventLogsObserver> observer; SetLocalLogsObserver(&observer); base::Optional<PeerConnectionKey> key; base::Optional<base::FilePath> file_path; - ON_CALL(observer, OnLocalLogsStarted(_, _)) + ON_CALL(observer, OnLocalLogStarted(_, _)) .WillByDefault(Invoke(SaveKeyAndFilePathTo(&key, &file_path))); ASSERT_TRUE(EnableLocalLogging()); @@ -836,12 +832,12 @@ TEST_F(WebRtcEventLogManagerTest, LocalLogFilenameMatchesExpectedFormat) { using StringType = base::FilePath::StringType; - NiceMock<MockLocalLogsObserver> observer; + NiceMock<MockWebRtcLocalEventLogsObserver> observer; SetLocalLogsObserver(&observer); base::Optional<PeerConnectionKey> key; base::Optional<base::FilePath> file_path; - ON_CALL(observer, OnLocalLogsStarted(_, _)) + ON_CALL(observer, OnLocalLogStarted(_, _)) .WillByDefault(Invoke(SaveKeyAndFilePathTo(&key, &file_path))); const base::Time::Exploded frozen_time_exploded{ @@ -884,13 +880,13 @@ LocalLogFilenameMatchesExpectedFormatRepeatedFilename) { using StringType = base::FilePath::StringType; - NiceMock<MockLocalLogsObserver> observer; + NiceMock<MockWebRtcLocalEventLogsObserver> observer; SetLocalLogsObserver(&observer); base::Optional<PeerConnectionKey> key; base::Optional<base::FilePath> file_path_1; base::Optional<base::FilePath> file_path_2; - EXPECT_CALL(observer, OnLocalLogsStarted(_, _)) + EXPECT_CALL(observer, OnLocalLogStarted(_, _)) .WillOnce(Invoke(SaveKeyAndFilePathTo(&key, &file_path_1))) .WillOnce(Invoke(SaveKeyAndFilePathTo(&key, &file_path_2)));
diff --git a/content/browser/webrtc/webrtc_local_event_log_manager.cc b/content/browser/webrtc/webrtc_local_event_log_manager.cc new file mode 100644 index 0000000..31bbc5d --- /dev/null +++ b/content/browser/webrtc/webrtc_local_event_log_manager.cc
@@ -0,0 +1,252 @@ +// Copyright (c) 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/webrtc/webrtc_local_event_log_manager.h" + +#include <limits> + +#include "base/files/file_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "build/build_config.h" + +#if defined(OS_WIN) +#define IntToStringType base::IntToString16 +#else +#define IntToStringType base::IntToString +#endif + +namespace content { + +#if defined(OS_ANDROID) +const size_t kDefaultMaxLocalLogFileSizeBytes = 10000000; +const size_t kMaxNumberLocalWebRtcEventLogFiles = 3; +#else +const size_t kDefaultMaxLocalLogFileSizeBytes = 60000000; +const size_t kMaxNumberLocalWebRtcEventLogFiles = 5; +#endif + +WebRtcLocalEventLogManager::WebRtcLocalEventLogManager( + WebRtcLocalEventLogsObserver* observer) + : observer_(observer), + clock_for_testing_(nullptr), + max_log_file_size_bytes_(kDefaultMaxLocalLogFileSizeBytes) {} + +WebRtcLocalEventLogManager::~WebRtcLocalEventLogManager() {} + +bool WebRtcLocalEventLogManager::PeerConnectionAdded(int render_process_id, + int lid) { + const auto result = active_peer_connections_.emplace(render_process_id, lid); + + if (!result.second) { // PeerConnection already registered. + return false; + } + + if (!base_path_.empty() && + log_files_.size() < kMaxNumberLocalWebRtcEventLogFiles) { + // Note that success/failure of starting the local log file is unrelated + // to the success/failure of PeerConnectionAdded(). + StartLogFile(render_process_id, lid); + } + + return true; +} + +bool WebRtcLocalEventLogManager::PeerConnectionRemoved(int render_process_id, + int lid) { + const PeerConnectionKey key = PeerConnectionKey(render_process_id, lid); + auto peer_connection = active_peer_connections_.find(key); + + if (peer_connection == active_peer_connections_.end()) { + DCHECK(log_files_.find(key) == log_files_.end()); + return false; + } + + auto local_log = log_files_.find(key); + if (local_log != log_files_.end()) { + // Note that success/failure of stopping the local log file is unrelated + // to the success/failure of PeerConnectionRemoved(). + StopLogFile(render_process_id, lid); + } + + active_peer_connections_.erase(peer_connection); + + return true; +} + +bool WebRtcLocalEventLogManager::EnableLogging(base::FilePath base_path, + size_t max_file_size_bytes) { + if (!base_path_.empty()) { + return false; + } + + DCHECK_EQ(log_files_.size(), 0u); + + base_path_ = base_path; + max_log_file_size_bytes_ = max_file_size_bytes; + + for (const PeerConnectionKey& peer_connection : active_peer_connections_) { + if (log_files_.size() >= kMaxNumberLocalWebRtcEventLogFiles) { + break; + } + StartLogFile(peer_connection.render_process_id, peer_connection.lid); + } + + return true; +} + +bool WebRtcLocalEventLogManager::DisableLogging() { + if (base_path_.empty()) { + return false; + } + + for (auto local_log = log_files_.begin(); local_log != log_files_.end();) { + local_log = CloseLogFile(local_log); + } + + base_path_.clear(); // Marks local-logging as disabled. + max_log_file_size_bytes_ = kDefaultMaxLocalLogFileSizeBytes; + + return true; +} + +bool WebRtcLocalEventLogManager::EventLogWrite(int render_process_id, + int lid, + const std::string& output) { + DCHECK_LE(output.length(), + static_cast<size_t>(std::numeric_limits<int>::max())); + + auto it = log_files_.find(PeerConnectionKey(render_process_id, lid)); + if (it == log_files_.end()) { + return false; + } + + // Observe the file size limit, if any. Note that base::File's interface does + // not allow writing more than numeric_limits<int>::max() bytes at a time. + int output_len = static_cast<int>(output.length()); // DCHECKed above. + LogFile& log_file = it->second; + if (log_file.max_file_size_bytes != kWebRtcEventLogManagerUnlimitedFileSize) { + DCHECK_LT(log_file.file_size_bytes, log_file.max_file_size_bytes); + if (log_file.file_size_bytes + output.length() < log_file.file_size_bytes || + log_file.file_size_bytes + output.length() > + log_file.max_file_size_bytes) { + output_len = log_file.max_file_size_bytes - log_file.file_size_bytes; + } + } + + int written = log_file.file.WriteAtCurrentPos(output.c_str(), output_len); + if (written < 0 || written != output_len) { // Error + LOG(WARNING) << "WebRTC event log output couldn't be written to local " + "file in its entirety."; + CloseLogFile(it); + return false; + } + + log_file.file_size_bytes += static_cast<size_t>(written); + if (log_file.max_file_size_bytes != kWebRtcEventLogManagerUnlimitedFileSize) { + DCHECK_LE(log_file.file_size_bytes, log_file.max_file_size_bytes); + if (log_file.file_size_bytes >= log_file.max_file_size_bytes) { + CloseLogFile(it); + } + } + + // Truncated output due to exceeding the maximum is reported as an error - the + // caller is interested to know that not all of its output was written, + // regardless of the reason. + return (static_cast<size_t>(written) == output.length()); +} + +void WebRtcLocalEventLogManager::InjectClockForTesting(base::Clock* clock) { + clock_for_testing_ = clock; +} + +void WebRtcLocalEventLogManager::StartLogFile(int render_process_id, int lid) { + // Add some information to the name given by the caller. + base::FilePath file_path = GetFilePath(base_path_, render_process_id, lid); + CHECK(!file_path.empty()) << "Couldn't set path for local WebRTC log file."; + + // In the unlikely case that this filename is already taken, find a unique + // number to append to the filename, if possible. + int unique_number = + base::GetUniquePathNumber(file_path, base::FilePath::StringType()); + if (unique_number < 0) { + return; // No available file path was found. + } else if (unique_number != 0) { + // The filename is taken, but a unique number was found. + // TODO(eladalon): Fix the way the unique number is used. + // https://crbug.com/785333 + file_path = file_path.InsertBeforeExtension(FILE_PATH_LITERAL(" (") + + IntToStringType(unique_number) + + FILE_PATH_LITERAL(")")); + } + + // Attempt to create the file. + constexpr int file_flags = base::File::FLAG_CREATE | base::File::FLAG_WRITE | + base::File::FLAG_EXCLUSIVE_WRITE; + base::File file(file_path, file_flags); + if (!file.IsValid() || !file.created()) { + LOG(WARNING) << "Couldn't create and/or open local WebRTC event log file."; + return; + } + + const PeerConnectionKey key(render_process_id, lid); + + // If the file was successfully created, it's now ready to be written to. + DCHECK(log_files_.find({render_process_id, lid}) == log_files_.end()); + log_files_.emplace(key, LogFile(std::move(file), max_log_file_size_bytes_)); + + // The observer needs to be able to run on any TaskQueue. + if (observer_) { + observer_->OnLocalLogStarted(key, file_path); + } +} + +void WebRtcLocalEventLogManager::StopLogFile(int render_process_id, int lid) { + auto it = log_files_.find(PeerConnectionKey(render_process_id, lid)); + if (it == log_files_.end()) { + return; + } + CloseLogFile(it); +} + +WebRtcLocalEventLogManager::LogFilesMap::iterator +WebRtcLocalEventLogManager::CloseLogFile(LogFilesMap::iterator it) { + const PeerConnectionKey peer_connection = it->first; + + it->second.file.Flush(); + it = log_files_.erase(it); // file.Close() called by destructor. + + if (observer_) { + observer_->OnLocalLogStopped(peer_connection); + } + + return it; +} + +base::FilePath WebRtcLocalEventLogManager::GetFilePath( + const base::FilePath& base_path, + int render_process_id, + int lid) { + base::Time::Exploded now; + if (clock_for_testing_) { + clock_for_testing_->Now().LocalExplode(&now); + } else { + base::Time::Now().LocalExplode(&now); + } + + // [user_defined]_[date]_[time]_[pid]_[lid].log + char stamp[100]; + int written = + base::snprintf(stamp, arraysize(stamp), "%04d%02d%02d_%02d%02d_%d_%d", + now.year, now.month, now.day_of_month, now.hour, + now.minute, render_process_id, lid); + CHECK_GT(written, 0); + CHECK_LT(static_cast<size_t>(written), arraysize(stamp)); + + return base_path.InsertBeforeExtension(FILE_PATH_LITERAL("_")) + .InsertBeforeExtensionASCII(base::StringPiece(stamp)) + .AddExtension(FILE_PATH_LITERAL("log")); +} + +} // namespace content
diff --git a/content/browser/webrtc/webrtc_local_event_log_manager.h b/content/browser/webrtc/webrtc_local_event_log_manager.h new file mode 100644 index 0000000..7934e028 --- /dev/null +++ b/content/browser/webrtc/webrtc_local_event_log_manager.h
@@ -0,0 +1,97 @@ +// Copyright (c) 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_WEBRTC_WEBRTC_LOCAL_EVENT_LOG_MANAGER_H_ +#define CONTENT_BROWSER_WEBRTC_WEBRTC_LOCAL_EVENT_LOG_MANAGER_H_ + +#include <map> +#include <set> +#include <string> + +#include "base/files/file.h" +#include "base/files/file_path.h" +#include "base/time/clock.h" +#include "content/browser/webrtc/webrtc_event_log_manager_common.h" + +namespace content { + +class WebRtcLocalEventLogManager { + public: + explicit WebRtcLocalEventLogManager(WebRtcLocalEventLogsObserver* observer); + ~WebRtcLocalEventLogManager(); + + bool PeerConnectionAdded(int render_process_id, int lid); + bool PeerConnectionRemoved(int render_process_id, int lid); + + bool EnableLogging(base::FilePath base_path, size_t max_file_size_bytes); + bool DisableLogging(); + + bool EventLogWrite(int render_process_id, int lid, const std::string& output); + + // This function is public, but this entire class is a protected + // implementation detail of WebRtcEventLogManager, which hides this + // function from everybody except its own unit-tests. + void InjectClockForTesting(base::Clock* clock); + + private: + using PeerConnectionKey = WebRtcEventLogPeerConnectionKey; + + struct LogFile { + LogFile(base::File file, size_t max_file_size_bytes) + : file(std::move(file)), + max_file_size_bytes(max_file_size_bytes), + file_size_bytes(0) {} + base::File file; + const size_t max_file_size_bytes; + size_t file_size_bytes; + }; + + typedef std::map<PeerConnectionKey, LogFile> LogFilesMap; + + // File handling. + void StartLogFile(int render_process_id, int lid); + void StopLogFile(int render_process_id, int lid); + LogFilesMap::iterator CloseLogFile(LogFilesMap::iterator it); + + // Derives the name of a local log file. The format is: + // [user_defined]_[date]_[time]_[pid]_[lid].log + base::FilePath GetFilePath(const base::FilePath& base_path, + int render_process_id, + int lid); + + // Observer which will be informed whenever a local log file is started or + // stopped. Through this, the owning WebRtcEventLogManager can be informed, + // and decide whether it wants to turn notifications from WebRTC on/off. + WebRtcLocalEventLogsObserver* const observer_; + + // For unit tests only, and specifically for unit tests that verify the + // filename format (derived from the current time as well as the renderer PID + // and PeerConnection local ID), we want to make sure that the time and date + // cannot change between the time the clock is read by the unit under test + // (namely WebRtcEventLogManager) and the time it's read by the test. + base::Clock* clock_for_testing_; + + // Currently active peer connections. PeerConnections which have been closed + // are not considered active, regardless of whether they have been torn down. + std::set<PeerConnectionKey> active_peer_connections_; + + // Local log files, stored at the behest of the user (via WebRTCInternals). + LogFilesMap log_files_; + + // If |base_path_| is empty, local logging is disabled. + // If nonempty, local logging is enabled, and all local logs will be saved + // to this directory. + base::FilePath base_path_; + + // The maximum size for local logs, in bytes. Note that + // kWebRtcEventLogManagerUnlimitedFileSize is a sentinel value (with a + // self-explanatory name). + size_t max_log_file_size_bytes_; + + DISALLOW_COPY_AND_ASSIGN(WebRtcLocalEventLogManager); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_WEBRTC_WEBRTC_LOCAL_EVENT_LOG_MANAGER_H_
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc index f8ca606..5bbd760 100644 --- a/content/child/child_thread_impl.cc +++ b/content/child/child_thread_impl.cc
@@ -34,6 +34,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/timer/elapsed_timer.h" #include "base/trace_event/memory_dump_manager.h" +#include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "components/tracing/child/child_trace_message_filter.h" #include "content/child/child_histogram_fetcher_impl.h" @@ -235,6 +236,7 @@ std::unique_ptr<mojo::edk::IncomingBrokerClientInvitation> InitializeMojoIPCChannel() { + TRACE_EVENT0("startup", "InitializeMojoIPCChannel"); mojo::edk::ScopedPlatformHandle platform_channel; #if defined(OS_WIN) if (base::CommandLine::ForCurrentProcess()->HasSwitch( @@ -431,6 +433,7 @@ } void ChildThreadImpl::Init(const Options& options) { + TRACE_EVENT0("startup", "ChildThreadImpl::Init"); g_lazy_tls.Pointer()->Set(this); on_channel_error_called_ = false; message_loop_ = base::MessageLoop::current();
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json index 4c6b49c..91cfe93 100644 --- a/content/public/app/mojo/content_browser_manifest.json +++ b/content/public/app/mojo/content_browser_manifest.json
@@ -161,10 +161,9 @@ "discardable_memory::mojom::DiscardableSharedMemoryManager", "media::mojom::ImageCapture", "media::mojom::InterfaceFactory", + "media::mojom::MediaMetricsProvider", "media::mojom::RemoterFactory", "media::mojom::Renderer", - "media::mojom::VideoDecodeStatsRecorder", - "media::mojom::WatchTimeRecorderProvider", "network::mojom::RestrictedCookieManager", "payments::mojom::PaymentManager", "payments::mojom::PaymentRequest", @@ -201,6 +200,7 @@ "blink::mojom::NotificationService", "blink::mojom::PermissionService", "blink::mojom::WebSocket", + "network::mojom::RestrictedCookieManager", "payments::mojom::PaymentManager", "shape_detection::mojom::BarcodeDetection", "shape_detection::mojom::FaceDetectionProvider",
diff --git a/content/public/app/mojo/content_renderer_manifest.json b/content/public/app/mojo/content_renderer_manifest.json index b9cd5a3..27388c4 100644 --- a/content/public/app/mojo/content_renderer_manifest.json +++ b/content/public/app/mojo/content_renderer_manifest.json
@@ -52,7 +52,8 @@ "content::mojom::ImageDownloader", "content::mojom::FrameInputHandler", "content::mojom::MediaStreamDispatcher", - "content::mojom::Widget" + "content::mojom::Widget", + "viz::mojom::InputTargetClient" ] }, "requires": {
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index b404fc8..c05d962 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -224,6 +224,7 @@ "render_widget_host_iterator.h", "render_widget_host_view.h", "render_widget_host_view_mac_delegate.h", + "replaced_navigation_entry_data.h", "resource_context.h", "resource_dispatcher_host.h", "resource_dispatcher_host_delegate.cc",
diff --git a/content/public/browser/gpu_data_manager.h b/content/public/browser/gpu_data_manager.h index d6db972a..33483d3 100644 --- a/content/public/browser/gpu_data_manager.h +++ b/content/public/browser/gpu_data_manager.h
@@ -82,11 +82,6 @@ const std::string& gl_renderer, const std::string& gl_version) = 0; - // Obtain collected GL strings. - virtual void GetGLStrings(std::string* gl_vendor, - std::string* gl_renderer, - std::string* gl_version) = 0; - // Turn off all hardware acceleration. virtual void DisableHardwareAcceleration() = 0;
diff --git a/content/public/browser/navigation_entry.h b/content/public/browser/navigation_entry.h index aca9f8e..2d81560 100644 --- a/content/public/browser/navigation_entry.h +++ b/content/public/browser/navigation_entry.h
@@ -11,6 +11,7 @@ #include <string> #include "base/memory/ref_counted_memory.h" +#include "base/optional.h" #include "base/strings/string16.h" #include "base/time/time.h" #include "build/build_config.h" @@ -26,6 +27,7 @@ class PageState; struct FaviconStatus; +struct ReplacedNavigationEntryData; struct SSLStatus; // A NavigationEntry is a data structure that captures all the information @@ -216,6 +218,12 @@ // redirecting URL to the final non-redirecting current URL. virtual void SetRedirectChain(const std::vector<GURL>& redirects) = 0; virtual const std::vector<GURL>& GetRedirectChain() const = 0; + // When a history entry is replaced (e.g. history.replaceState()), this + // contains some information about the entry prior to being replaced. Even if + // an entry is replaced multiple times, it represents data prior to the + // *first* replace. + virtual const base::Optional<ReplacedNavigationEntryData>& + GetReplacedEntryData() const = 0; // True if this entry is restored and hasn't been loaded. virtual bool IsRestored() const = 0;
diff --git a/content/public/browser/render_process_host_factory.h b/content/public/browser/render_process_host_factory.h index 78ff77e..7705418 100644 --- a/content/public/browser/render_process_host_factory.h +++ b/content/public/browser/render_process_host_factory.h
@@ -10,6 +10,7 @@ namespace content { class BrowserContext; class RenderProcessHost; +class SiteInstance; // Factory object for RenderProcessHosts. Using this factory allows tests to // swap out a different one to use a TestRenderProcessHost. @@ -17,7 +18,8 @@ public: virtual ~RenderProcessHostFactory() {} virtual RenderProcessHost* CreateRenderProcessHost( - BrowserContext* browser_context) const = 0; + BrowserContext* browser_context, + SiteInstance* site_instance) const = 0; }; } // namespace content
diff --git a/content/public/browser/replaced_navigation_entry_data.h b/content/public/browser/replaced_navigation_entry_data.h new file mode 100644 index 0000000..ccc9cbf --- /dev/null +++ b/content/public/browser/replaced_navigation_entry_data.h
@@ -0,0 +1,60 @@ +// Copyright (c) 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_PUBLIC_BROWSER_REPLACED_NAVIGATION_ENTRY_DATA_H_ +#define CONTENT_PUBLIC_BROWSER_REPLACED_NAVIGATION_ENTRY_DATA_H_ + +#include "base/time/time.h" +#include "ui/base/page_transition_types.h" +#include "url/gurl.h" + +namespace content { + +// Represents a subset of NavigationEntry's fields, stored in this structure for +// the cases where a navigation has been replaced (e.g. history.replaceState()) +// and the original values must be remembered. The main goal is to make sure +// important user-initiated navigations like PAGE_TRANSITION_TYPED and +// PAGE_TRANSITION_AUTO_BOOKMARK are not "lost" due to later replacements. +// +// Things worth pointing out: +// - This is the first commit that happens for a given NavigationEntry, before +// any client redirects, location.replace() events, or history.replaceState() +// events. +// +// - This URL might not be the same as the first entry in the original redirect +// chain (aka original_request_url), since it represents the landing URL in +// the original server-side redirect chain. +// +// - The value is preserved for navigations modifying history, including: +// a) Cross-document replacement navigations which generate a new +// NavigationEntry with replacement (e.g. client redirects and +// location.replace()). +// b) Same-document cases that update the existing NavigationEntry (e.g. +// history.replaceState()). +// +// - Keeping a single value of this struct (per navigation controller index) is +// generally sufficient because the relevant page transition that we care +// about (PAGE_TRANSITION_TYPED and PAGE_TRANSITION_AUTO_BOOKMARK) always +// create a new entry. +// +// The concept is valid for subframe navigations but we only need to track it +// for main frame navigations. +struct ReplacedNavigationEntryData { + // Analogous to NavigationEntry::GetURL(), at the time of the first commit, + // prior to any replacements. Note that, in the event of server-side + // redirects, it stores the landing URL. + GURL first_committed_url; + // Analogous to NavigationEntry::GetTimestamp(), at the time of the first + // commit, prior to any replacements. This is useful during analysis of + // sync-ed history to distinguish whether the entry prior to being replaced + // was sync-ed or not. + base::Time first_timestamp; + // Analogous to NavigationEntry::GetTransitionType(), at the time of the first + // commit, prior to any replacements. + ui::PageTransition first_transition_type; +}; + +} // namespace content + +#endif // CONTENT_PUBLIC_BROWSER_REPLACED_NAVIGATION_ENTRY_DATA_H_
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index f21b4f3c..27e9edb 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -321,7 +321,7 @@ // An experiment to require process isolation for the sign-in origin, // https://accounts.google.com. Launch bug: https://crbug.com/739418. const base::Feature kSignInProcessIsolation{"sign-in-process-isolation", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; // Alternative to switches::kSitePerProcess, for turning on full site isolation. // Launch bug: https://crbug.com/739418.
diff --git a/content/public/test/mock_render_process_host.cc b/content/public/test/mock_render_process_host.cc index 5e3e85b..5aa4c51 100644 --- a/content/public/test/mock_render_process_host.cc +++ b/content/public/test/mock_render_process_host.cc
@@ -32,6 +32,7 @@ #include "content/public/browser/notification_source.h" #include "content/public/browser/notification_types.h" #include "content/public/browser/render_widget_host_iterator.h" +#include "content/public/browser/site_instance.h" #include "content/public/browser/storage_partition.h" #include "content/public/common/service_manager_connection.h" #include "content/public/common/service_names.mojom.h" @@ -445,14 +446,15 @@ MockRenderProcessHostFactory::MockRenderProcessHostFactory() {} MockRenderProcessHostFactory::~MockRenderProcessHostFactory() { - // Detach this object from MockRenderProcesses to prevent STLDeleteElements() - // from calling MockRenderProcessHostFactory::Remove(). + // Detach this object from MockRenderProcesses to prevent them from calling + // MockRenderProcessHostFactory::Remove() when destroyed. for (const auto& process : processes_) process->SetFactory(nullptr); } RenderProcessHost* MockRenderProcessHostFactory::CreateRenderProcessHost( - BrowserContext* browser_context) const { + BrowserContext* browser_context, + SiteInstance* site_instance) const { processes_.push_back( std::make_unique<MockRenderProcessHost>(browser_context)); processes_.back()->SetFactory(this);
diff --git a/content/public/test/mock_render_process_host.h b/content/public/test/mock_render_process_host.h index 44f3907..6d19cd2 100644 --- a/content/public/test/mock_render_process_host.h +++ b/content/public/test/mock_render_process_host.h
@@ -30,6 +30,7 @@ #include "services/service_manager/public/cpp/interface_provider.h" class StoragePartition; +class SiteInstance; namespace content { @@ -222,7 +223,8 @@ ~MockRenderProcessHostFactory() override; RenderProcessHost* CreateRenderProcessHost( - BrowserContext* browser_context) const override; + BrowserContext* browser_context, + SiteInstance* site_instance) const override; // Removes the given MockRenderProcessHost from the MockRenderProcessHost list // without deleting it. When a test deletes a MockRenderProcessHost, we need
diff --git a/content/public/test/navigation_simulator.cc b/content/public/test/navigation_simulator.cc index 791505a..e7d6054f 100644 --- a/content/public/test/navigation_simulator.cc +++ b/content/public/test/navigation_simulator.cc
@@ -237,6 +237,7 @@ browser_initiated_(browser_initiated), transition_(browser_initiated ? ui::PAGE_TRANSITION_TYPED : ui::PAGE_TRANSITION_LINK), + contents_mime_type_("text/html"), weak_factory_(this) { // For renderer-initiated navigation, the RenderFrame must be initialized. Do // it if it hasn't happened yet. @@ -471,7 +472,7 @@ params.did_create_new_entry = DidCreateNewEntry(); params.gesture = has_user_gesture_ ? NavigationGestureUser : NavigationGestureAuto; - params.contents_mime_type = "text/html"; + params.contents_mime_type = contents_mime_type_; params.method = "GET"; params.http_status_code = 200; params.history_list_was_cleared = false; @@ -641,7 +642,7 @@ params.did_create_new_entry = false; params.gesture = has_user_gesture_ ? NavigationGestureUser : NavigationGestureAuto; - params.contents_mime_type = "text/html"; + params.contents_mime_type = contents_mime_type_; params.method = "GET"; params.http_status_code = 200; params.history_list_was_cleared = false; @@ -713,6 +714,13 @@ interface_provider_request_ = std::move(request); } +void NavigationSimulator::SetContentsMimeType( + const std::string& contents_mime_type) { + CHECK_LE(state_, STARTED) << "The contents mime type cannot be set after the " + "navigation has committed or failed"; + contents_mime_type_ = contents_mime_type; +} + NavigationThrottle::ThrottleCheckResult NavigationSimulator::GetLastThrottleCheckResult() { return last_throttle_check_result_.value();
diff --git a/content/public/test/navigation_simulator.h b/content/public/test/navigation_simulator.h index 23955ff..3f87130f 100644 --- a/content/public/test/navigation_simulator.h +++ b/content/public/test/navigation_simulator.h
@@ -233,6 +233,10 @@ virtual void SetInterfaceProviderRequest( service_manager::mojom::InterfaceProviderRequest request); + // Provides the contents mime type to be set at commit. It should be + // specified before calling |Commit|. + virtual void SetContentsMimeType(const std::string& contents_mime_type); + // -------------------------------------------------------------------------- // Gets the last throttle check result computed by the navigation throttles. @@ -352,6 +356,7 @@ int session_history_offset_ = 0; bool has_user_gesture_ = true; service_manager::mojom::InterfaceProviderRequest interface_provider_request_; + std::string contents_mime_type_; // These are used to sanity check the content/public/ API calls emitted as // part of the navigation.
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index 962d6a0..68c7c0f 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -94,8 +94,6 @@ "device_sensors/device_sensor_event_pump.h", "devtools/devtools_agent.cc", "devtools/devtools_agent.h", - "devtools/devtools_cpu_throttler.cc", - "devtools/devtools_cpu_throttler.h", "devtools/render_widget_screen_metrics_emulator.cc", "devtools/render_widget_screen_metrics_emulator.h", "devtools/render_widget_screen_metrics_emulator_delegate.h", @@ -206,6 +204,8 @@ "input/input_handler_manager_client.h", "input/input_handler_wrapper.cc", "input/input_handler_wrapper.h", + "input/input_target_client_impl.cc", + "input/input_target_client_impl.h", "input/main_thread_event_queue.cc", "input/main_thread_event_queue.h", "input/main_thread_event_queue_task.h", @@ -459,12 +459,8 @@ "service_worker/service_worker_type_converters.h", "service_worker/service_worker_type_util.cc", "service_worker/service_worker_type_util.h", - "service_worker/thread_safe_script_container.cc", - "service_worker/thread_safe_script_container.h", "service_worker/web_service_worker_impl.cc", "service_worker/web_service_worker_impl.h", - "service_worker/web_service_worker_installed_scripts_manager_impl.cc", - "service_worker/web_service_worker_installed_scripts_manager_impl.h", "service_worker/web_service_worker_provider_impl.cc", "service_worker/web_service_worker_provider_impl.h", "service_worker/web_service_worker_registration_impl.cc",
diff --git a/content/renderer/devtools/devtools_agent.cc b/content/renderer/devtools/devtools_agent.cc index 6342ce5..73fa2ea 100644 --- a/content/renderer/devtools/devtools_agent.cc +++ b/content/renderer/devtools/devtools_agent.cc
@@ -13,12 +13,10 @@ #include "base/lazy_instance.h" #include "base/strings/string_number_conversions.h" #include "base/threading/thread_task_runner_handle.h" -#include "base/trace_event/trace_event.h" #include "content/child/child_process.h" #include "content/common/devtools_messages.h" #include "content/common/frame_messages.h" #include "content/public/common/manifest.h" -#include "content/renderer/devtools/devtools_cpu_throttler.h" #include "content/renderer/render_frame_impl.h" #include "content/renderer/render_widget.h" #include "ipc/ipc_channel.h" @@ -43,7 +41,6 @@ // TODO(dgozman): somehow get this from a mojo config. // See kMaximumMojoMessageSize in services/service_manager/embedder/main.cc. const size_t kMaxDevToolsMessageChunkSize = 128 * 1024 * 1024 / 4; -const char kPageGetAppManifest[] = "Page.getAppManifest"; } // namespace @@ -163,10 +160,6 @@ DevToolsAgent::~DevToolsAgent() { } -void DevToolsAgent::WidgetWillClose() { - ContinueProgram(); -} - void DevToolsAgent::OnDestruct() { delete this; } @@ -241,27 +234,6 @@ return true; } -void DevToolsAgent::EnableTracing(const WebString& category_filter) { - // Tracing is already started by DevTools TracingHandler::Start for the - // renderer target in the browser process. It will eventually start tracing in - // the renderer process via IPC. But we still need a redundant - // TraceLog::SetEnabled call here for - // InspectorTracingAgent::emitMetadataEvents(), at which point, we are not - // sure if tracing is already started in the renderer process. - TraceLog* trace_log = TraceLog::GetInstance(); - trace_log->SetEnabled( - base::trace_event::TraceConfig(category_filter.Utf8(), ""), - TraceLog::RECORDING_MODE); -} - -void DevToolsAgent::DisableTracing() { - TraceLog::GetInstance()->SetDisabled(); -} - -void DevToolsAgent::SetCPUThrottlingRate(double rate) { - DevToolsCPUThrottler::GetInstance()->SetThrottlingRate(rate); -} - void DevToolsAgent::SendChunkedProtocolMessage(int session_id, int call_id, std::string message, @@ -297,12 +269,6 @@ const std::string& method, const std::string& message) { TRACE_EVENT0("devtools", "DevToolsAgent::DispatchOnInspectorBackend"); - if (method == kPageGetAppManifest) { - frame_->GetManifestManager().RequestManifestDebugInfo( - base::BindOnce(&DevToolsAgent::GotManifest, weak_factory_.GetWeakPtr(), - session_id, call_id)); - return; - } GetWebAgent()->DispatchOnInspectorBackend(session_id, call_id, WebString::FromUTF8(method), WebString::FromUTF8(message)); @@ -348,40 +314,4 @@ sessions_.clear(); } -void DevToolsAgent::GotManifest(int session_id, - int call_id, - const GURL& manifest_url, - blink::mojom::ManifestDebugInfoPtr debug_info) { - std::unique_ptr<base::DictionaryValue> response(new base::DictionaryValue()); - response->SetInteger("id", call_id); - std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue()); - std::unique_ptr<base::ListValue> errors(new base::ListValue()); - - bool failed = false; - if (debug_info) { - for (const auto& error : debug_info->errors) { - std::unique_ptr<base::DictionaryValue> error_value( - new base::DictionaryValue()); - error_value->SetString("message", error->message); - error_value->SetBoolean("critical", error->critical); - error_value->SetInteger("line", error->line); - error_value->SetInteger("column", error->column); - if (error->critical) - failed = true; - errors->Append(std::move(error_value)); - } - if (!failed) - result->SetString("data", debug_info->raw_manifest); - } - - result->SetString("url", manifest_url.possibly_invalid_spec()); - result->Set("errors", std::move(errors)); - response->Set("result", std::move(result)); - - std::string json_message; - base::JSONWriter::Write(*response, &json_message); - SendChunkedProtocolMessage(session_id, call_id, std::move(json_message), - std::string()); -} - } // namespace content
diff --git a/content/renderer/devtools/devtools_agent.h b/content/renderer/devtools/devtools_agent.h index d699c8ba..eec8ef5 100644 --- a/content/renderer/devtools/devtools_agent.h +++ b/content/renderer/devtools/devtools_agent.h
@@ -17,15 +17,12 @@ #include "content/common/devtools.mojom.h" #include "content/public/renderer/render_frame_observer.h" #include "mojo/public/cpp/bindings/associated_binding.h" -#include "third_party/WebKit/public/platform/modules/manifest/manifest.mojom.h" #include "third_party/WebKit/public/web/WebDevToolsAgentClient.h" namespace blink { class WebDevToolsAgent; } -class GURL; - namespace content { class RenderFrameImpl; @@ -51,7 +48,6 @@ class MessageImpl; // RenderFrameObserver implementation. - void WidgetWillClose() override; void OnDestruct() override; // mojom::DevToolsAgent implementation. @@ -70,9 +66,6 @@ void DidExitDebugLoop() override; bool RequestDevToolsForFrame(int session_id, blink::WebLocalFrame* frame) override; - void EnableTracing(const blink::WebString& category_filter) override; - void DisableTracing() override; - void SetCPUThrottlingRate(double rate) override; void DetachSession(int session_id); blink::WebDevToolsAgent* GetWebAgent(); @@ -82,10 +75,6 @@ const std::string& message); void InspectElement(int session_id, const gfx::Point& point); void OnRequestNewWindowCompleted(int session_id, bool success); - void GotManifest(int session_id, - int command_id, - const GURL& manifest_url, - blink::mojom::ManifestDebugInfoPtr debug_info); void SendChunkedProtocolMessage(int session_id, int call_id, std::string message,
diff --git a/content/renderer/devtools/devtools_cpu_throttler.h b/content/renderer/devtools/devtools_cpu_throttler.h deleted file mode 100644 index 169575a..0000000 --- a/content/renderer/devtools/devtools_cpu_throttler.h +++ /dev/null
@@ -1,40 +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 CONTENT_RENDERER_DEVTOOLS_DEVTOOLS_CPU_THROTTLER_H_ -#define CONTENT_RENDERER_DEVTOOLS_DEVTOOLS_CPU_THROTTLER_H_ - -#include <memory> - -#include "base/macros.h" -#include "content/common/content_export.h" - -namespace base { -template <typename T> -struct DefaultSingletonTraits; -}; - -namespace content { - -class CPUThrottlingThread; - -// Singleton that manages creation of the throttler thread. -class CONTENT_EXPORT DevToolsCPUThrottler final { - public: - void SetThrottlingRate(double rate); - static DevToolsCPUThrottler* GetInstance(); - - private: - DevToolsCPUThrottler(); - ~DevToolsCPUThrottler(); - friend struct base::DefaultSingletonTraits<DevToolsCPUThrottler>; - - std::unique_ptr<CPUThrottlingThread> throttling_thread_; - - DISALLOW_COPY_AND_ASSIGN(DevToolsCPUThrottler); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_DEVTOOLS_DEVTOOLS_CPU_THROTTLER_H_
diff --git a/content/renderer/input/input_handler_wrapper.cc b/content/renderer/input/input_handler_wrapper.cc index af23c3f..a00a763 100644 --- a/content/renderer/input/input_handler_wrapper.cc +++ b/content/renderer/input/input_handler_wrapper.cc
@@ -43,14 +43,6 @@ base::BindOnce(&RenderWidget::SetNeedsMainFrame, render_widget_)); } -void InputHandlerWrapper::TransferActiveWheelFlingAnimation( - const blink::WebActiveWheelFlingParameters& params) { - main_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&RenderWidget::TransferActiveWheelFlingAnimation, - render_widget_, params)); -} - void InputHandlerWrapper::DispatchNonBlockingEventToMainThread( ui::WebScopedInputEvent event, const ui::LatencyInfo& latency_info) {
diff --git a/content/renderer/input/input_handler_wrapper.h b/content/renderer/input/input_handler_wrapper.h index 4f849f8de..e5ddaad 100644 --- a/content/renderer/input/input_handler_wrapper.h +++ b/content/renderer/input/input_handler_wrapper.h
@@ -40,8 +40,6 @@ // InputHandlerProxyClient implementation. void WillShutdown() override; - void TransferActiveWheelFlingAnimation( - const blink::WebActiveWheelFlingParameters& params) override; void DispatchNonBlockingEventToMainThread( ui::WebScopedInputEvent event, const ui::LatencyInfo& latency_info) override;
diff --git a/content/renderer/input/input_target_client_impl.cc b/content/renderer/input/input_target_client_impl.cc new file mode 100644 index 0000000..1ce6116 --- /dev/null +++ b/content/renderer/input/input_target_client_impl.cc
@@ -0,0 +1,32 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/input/input_target_client_impl.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "content/renderer/render_frame_impl.h" +#include "content/renderer/render_widget.h" + +namespace content { + +InputTargetClientImpl::InputTargetClientImpl(RenderFrameImpl* render_frame) + : render_frame_(render_frame), binding_(this) {} + +InputTargetClientImpl::~InputTargetClientImpl() {} + +void InputTargetClientImpl::BindToRequest( + viz::mojom::InputTargetClientRequest request) { + DCHECK(!binding_.is_bound()); + binding_.Bind(std::move(request)); +} + +void InputTargetClientImpl::FrameSinkIdAt(const gfx::Point& point, + FrameSinkIdAtCallback callback) { + std::move(callback).Run(viz::FrameSinkId( + RenderThread::Get()->GetClientId(), + render_frame_->GetRenderWidget()->GetWidgetRoutingIdAtPoint(point))); +} + +} // namespace content
diff --git a/content/renderer/input/input_target_client_impl.h b/content/renderer/input/input_target_client_impl.h new file mode 100644 index 0000000..fce5832 --- /dev/null +++ b/content/renderer/input/input_target_client_impl.h
@@ -0,0 +1,37 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_INPUT_INPUT_TARGET_CLIENT_IMPL_H_ +#define CONTENT_RENDERER_INPUT_INPUT_TARGET_CLIENT_IMPL_H_ + +#include "mojo/public/cpp/bindings/binding.h" +#include "services/viz/public/interfaces/hit_test/input_target_client.mojom.h" + +namespace content { + +class RenderFrameImpl; + +// This class provides an implementation of InputTargetClient mojo interface. +class InputTargetClientImpl : public viz::mojom::InputTargetClient { + public: + explicit InputTargetClientImpl(RenderFrameImpl* render_frame); + ~InputTargetClientImpl() override; + + void BindToRequest(viz::mojom::InputTargetClientRequest request); + + // viz::mojom::InputTargetClient: + void FrameSinkIdAt(const gfx::Point& point, + FrameSinkIdAtCallback callback) override; + + private: + RenderFrameImpl* const render_frame_; + + mojo::Binding<viz::mojom::InputTargetClient> binding_; + + DISALLOW_COPY_AND_ASSIGN(InputTargetClientImpl); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_INPUT_INPUT_TARGET_CLIENT_IMPL_H_
diff --git a/content/renderer/input/render_widget_input_handler.cc b/content/renderer/input/render_widget_input_handler.cc index 04af76f..420ae6f3 100644 --- a/content/renderer/input/render_widget_input_handler.cc +++ b/content/renderer/input/render_widget_input_handler.cc
@@ -33,6 +33,7 @@ #include "third_party/WebKit/public/web/WebLocalFrame.h" #include "third_party/WebKit/public/web/WebNode.h" #include "ui/events/blink/web_input_event_traits.h" +#include "ui/gfx/geometry/dip_util.h" #include "ui/gfx/geometry/point_conversions.h" #include "ui/latency/latency_info.h" @@ -159,10 +160,13 @@ int RenderWidgetInputHandler::GetWidgetRoutingIdAtPoint( const gfx::Point& point) { - blink::WebNode result_node = - widget_->GetWebWidget() - ->HitTestResultAt(blink::WebPoint(point.x(), point.y())) - .GetNode(); + gfx::PointF point_in_pixel = + gfx::ConvertPointToPixel(widget_->GetOriginalDeviceScaleFactor(), + gfx::PointF(point.x(), point.y())); + blink::WebNode result_node = widget_->GetWebWidget() + ->HitTestResultAt(blink::WebPoint( + point_in_pixel.x(), point_in_pixel.y())) + .GetNode(); blink::WebFrame* result_frame = blink::WebFrame::FromFrameOwnerElement(result_node);
diff --git a/content/renderer/input/widget_input_handler_manager.cc b/content/renderer/input/widget_input_handler_manager.cc index 4a20df3b..ed5570f 100644 --- a/content/renderer/input/widget_input_handler_manager.cc +++ b/content/renderer/input/widget_input_handler_manager.cc
@@ -118,14 +118,6 @@ input_handler_proxy_.reset(); } -void WidgetInputHandlerManager::TransferActiveWheelFlingAnimation( - const blink::WebActiveWheelFlingParameters& params) { - main_thread_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&RenderWidget::TransferActiveWheelFlingAnimation, - render_widget_, params)); -} - void WidgetInputHandlerManager::DispatchNonBlockingEventToMainThread( ui::WebScopedInputEvent event, const ui::LatencyInfo& latency_info) {
diff --git a/content/renderer/input/widget_input_handler_manager.h b/content/renderer/input/widget_input_handler_manager.h index d29015e..6c44b42 100644 --- a/content/renderer/input/widget_input_handler_manager.h +++ b/content/renderer/input/widget_input_handler_manager.h
@@ -42,8 +42,6 @@ // InputHandlerProxyClient overrides. void WillShutdown() override; - void TransferActiveWheelFlingAnimation( - const blink::WebActiveWheelFlingParameters& params) override; void DispatchNonBlockingEventToMainThread( ui::WebScopedInputEvent event, const ui::LatencyInfo& latency_info) override;
diff --git a/content/renderer/media/android/stream_texture_wrapper_impl.cc b/content/renderer/media/android/stream_texture_wrapper_impl.cc index 18f240e7..b26079e 100644 --- a/content/renderer/media/android/stream_texture_wrapper_impl.cc +++ b/content/renderer/media/android/stream_texture_wrapper_impl.cc
@@ -72,18 +72,16 @@ GLuint texture_target = GL_TEXTURE_EXTERNAL_OES; GLuint texture_id_ref = gl->CreateAndConsumeTextureCHROMIUM(texture_mailbox_.name); - const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM(); gl->Flush(); gpu::SyncToken texture_mailbox_sync_token; - gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, - texture_mailbox_sync_token.GetData()); if (texture_mailbox_sync_token.namespace_id() == gpu::CommandBufferNamespace::IN_PROCESS) { // TODO(boliu): Remove this once Android WebView switches to IPC-based // command buffer for video. - GLbyte* sync_tokens[] = {texture_mailbox_sync_token.GetData()}; - gl->VerifySyncTokensCHROMIUM(sync_tokens, arraysize(sync_tokens)); + gl->GenSyncTokenCHROMIUM(texture_mailbox_sync_token.GetData()); + } else { + gl->GenUnverifiedSyncTokenCHROMIUM(texture_mailbox_sync_token.GetData()); } gpu::MailboxHolder holders[media::VideoFrame::kMaxPlanes] = {
diff --git a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc index 628bb99..aa674e2 100644 --- a/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc +++ b/content/renderer/media/gpu/gpu_video_accelerator_factories_impl.cc
@@ -248,9 +248,7 @@ viz::ContextProvider::ScopedContextLock lock(context_provider_); gpu::gles2::GLES2Interface* gl = lock.ContextGL(); gpu::SyncToken sync_token; - const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM(); - gl->ShallowFlushCHROMIUM(); - gl->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + gl->GenSyncTokenCHROMIUM(sync_token.GetData()); return sync_token; }
diff --git a/content/renderer/pepper/pepper_graphics_2d_host.cc b/content/renderer/pepper/pepper_graphics_2d_host.cc index e3b9a839..4ca26ec 100644 --- a/content/renderer/pepper/pepper_graphics_2d_host.cc +++ b/content/renderer/pepper/pepper_graphics_2d_host.cc
@@ -749,9 +749,7 @@ swizzled.reset(); gpu::SyncToken sync_token; - uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM(); - gl->OrderingBarrierCHROMIUM(); - gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + gl->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); gl->BindTexture(texture_target, 0);
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 18a1ce8..d3bb3d87 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -108,6 +108,7 @@ #include "content/renderer/ime_event_guard.h" #include "content/renderer/input/frame_input_handler_impl.h" #include "content/renderer/input/input_handler_manager.h" +#include "content/renderer/input/input_target_client_impl.h" #include "content/renderer/installedapp/related_apps_fetcher.h" #include "content/renderer/internal_document_state_data.h" #include "content/renderer/loader/request_extra_data.h" @@ -1313,6 +1314,7 @@ media_factory_(this, base::Bind(&RenderFrameImpl::RequestOverlayRoutingToken, base::Unretained(this))), + input_target_client_impl_(this), devtools_frame_token_( blink::WebString::FromUTF8(params.devtools_frame_token.ToString())), weak_factory_(this) { @@ -7076,6 +7078,10 @@ weak_factory_.GetWeakPtr())); registry_.AddInterface( + base::Bind(&InputTargetClientImpl::BindToRequest, + base::Unretained(&input_target_client_impl_))); + + registry_.AddInterface( base::Bind(&RenderFrameImpl::BindWidget, weak_factory_.GetWeakPtr())); if (!frame_->Parent()) {
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 85d16b2..a2c6b8d 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -50,6 +50,7 @@ #include "content/public/common/url_loader_factory.mojom.h" #include "content/public/renderer/render_frame.h" #include "content/renderer/frame_blame_context.h" +#include "content/renderer/input/input_target_client_impl.h" #include "content/renderer/media/media_factory.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/renderer_webcookiejar_impl.h" @@ -1593,6 +1594,8 @@ // Callbacks that we should call when we get a routing token. std::vector<media::RoutingTokenCallback> pending_routing_token_callbacks_; + InputTargetClientImpl input_target_client_impl_; + RenderThreadImpl::RendererMemoryMetrics peak_memory_metrics_; // Used for devtools instrumentation and trace-ability. This token is
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 748d24d..dec83a6 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -572,6 +572,7 @@ // static RenderThreadImpl* RenderThreadImpl::Create( const InProcessChildThreadParams& params) { + TRACE_EVENT0("startup", "RenderThreadImpl::Create"); std::unique_ptr<blink::scheduler::RendererScheduler> renderer_scheduler = blink::scheduler::RendererScheduler::Create(); scoped_refptr<base::SingleThreadTaskRunner> test_task_counter; @@ -583,6 +584,7 @@ RenderThreadImpl* RenderThreadImpl::Create( std::unique_ptr<base::MessageLoop> main_message_loop, std::unique_ptr<blink::scheduler::RendererScheduler> renderer_scheduler) { + TRACE_EVENT0("startup", "RenderThreadImpl::Create"); return new RenderThreadImpl(std::move(main_message_loop), std::move(renderer_scheduler)); } @@ -1510,7 +1512,10 @@ scoped_refptr<base::SingleThreadTaskRunner> media_task_runner = GetMediaThreadTaskRunner(); const bool enable_video_accelerator = - !cmd_line->HasSwitch(switches::kDisableAcceleratedVideoDecode); + !cmd_line->HasSwitch(switches::kDisableAcceleratedVideoDecode) && + (gpu_channel_host->gpu_feature_info() + .status_values[gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE] == + gpu::kGpuFeatureStatusEnabled); const bool enable_gpu_memory_buffer_video_frames = !is_gpu_compositing_disabled_ && #if defined(OS_MACOSX) || defined(OS_LINUX)
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index 6e8927f..7d690bf 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -2609,24 +2609,6 @@ #endif -TEST_F(DevToolsAgentTest, DevToolsResumeOnClose) { - Attach(); - EXPECT_FALSE(IsPaused()); - DispatchDevToolsMessage("Debugger.enable", - "{\"id\":1,\"method\":\"Debugger.enable\"}"); - - // Executing javascript will pause the thread and create nested run loop. - // Posting task simulates message coming from browser. - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&DevToolsAgentTest::CloseWhilePaused, - base::Unretained(this))); - ExecuteJavaScriptForTests("debugger;"); - - // CloseWhilePaused should resume execution and continue here. - EXPECT_FALSE(IsPaused()); - Detach(); -} - TEST_F(DevToolsAgentTest, RuntimeEnableForcesContexts) { LoadHTML("<body>page<iframe></iframe></body>"); Attach();
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 0dc04e7..8bc3129 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -2048,15 +2048,6 @@ } } -void RenderWidget::TransferActiveWheelFlingAnimation( - const blink::WebActiveWheelFlingParameters& params) { - blink::WebWidget* web_widget = GetWebWidget(); - if (web_widget && web_widget->IsWebFrameWidget()) { - static_cast<blink::WebFrameWidget*>(web_widget) - ->TransferActiveWheelFlingAnimation(params); - } -} - void RenderWidget::OnRequestTextInputStateUpdate() { #if defined(OS_ANDROID) DCHECK(!ime_event_guard_);
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index e0b8c81..3753bcc 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -75,7 +75,6 @@ namespace scheduler { class RenderWidgetSchedulingState; } -struct WebActiveWheelFlingParameters; struct WebDeviceEmulationParams; class WebDragData; class WebFrameWidget; @@ -405,9 +404,6 @@ gfx::PointF ConvertWindowPointToViewport(const gfx::PointF& point); gfx::Point ConvertWindowPointToViewport(const gfx::Point& point); - void TransferActiveWheelFlingAnimation( - const blink::WebActiveWheelFlingParameters& params); - uint32_t GetContentSourceId(); void IncrementContentSourceId();
diff --git a/content/renderer/renderer_main_platform_delegate_android.cc b/content/renderer/renderer_main_platform_delegate_android.cc index b433720..44f2588d 100644 --- a/content/renderer/renderer_main_platform_delegate_android.cc +++ b/content/renderer/renderer_main_platform_delegate_android.cc
@@ -6,6 +6,7 @@ #include "base/android/build_info.h" #include "base/metrics/histogram_macros.h" +#include "base/trace_event/trace_event.h" #include "content/renderer/seccomp_sandbox_status_android.h" #include "sandbox/linux/seccomp-bpf-helpers/seccomp_starter_android.h" #include "sandbox/sandbox_features.h" @@ -30,6 +31,7 @@ } bool RendererMainPlatformDelegate::EnableSandbox() { + TRACE_EVENT0("startup", "RendererMainPlatformDelegate::EnableSandbox"); auto* info = base::android::BuildInfo::GetInstance(); sandbox::SeccompStarterAndroid starter(info->sdk_int(), info->device()); // The policy compiler is only available if USE_SECCOMP_BPF is enabled.
diff --git a/content/renderer/service_worker/embedded_worker_instance_client_impl.cc b/content/renderer/service_worker/embedded_worker_instance_client_impl.cc index a5f666b8..ebe6c6d1 100644 --- a/content/renderer/service_worker/embedded_worker_instance_client_impl.cc +++ b/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
@@ -15,11 +15,9 @@ #include "content/public/common/content_client.h" #include "content/renderer/service_worker/embedded_worker_devtools_agent.h" #include "content/renderer/service_worker/service_worker_context_client.h" -#include "content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h" #include "third_party/WebKit/public/platform/WebContentSettingsClient.h" #include "third_party/WebKit/public/platform/WebSecurityOrigin.h" #include "third_party/WebKit/public/platform/WebURL.h" -#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h" #include "third_party/WebKit/public/web/WebEmbeddedWorker.h" #include "third_party/WebKit/public/web/WebEmbeddedWorkerStartData.h" @@ -135,19 +133,29 @@ std::unique_ptr<ServiceWorkerContextClient> context_client, blink::mojom::WorkerContentSettingsProxyPtr content_settings_proxy, service_manager::mojom::InterfaceProviderPtr interface_provider) { - std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManager> manager; + std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManagerParams> + installed_scripts_manager_params; // |installed_scripts_info| is null if scripts should be served by net layer, // when the worker is not installed, or the worker is launched for checking // the update. if (ServiceWorkerUtils::IsScriptStreamingEnabled() && installed_scripts_info) { - manager = WebServiceWorkerInstalledScriptsManagerImpl::Create( - std::move(installed_scripts_info), io_thread_runner_); + installed_scripts_manager_params = std::make_unique< + blink::WebServiceWorkerInstalledScriptsManagerParams>(); + installed_scripts_manager_params->installed_scripts_urls = + std::move(installed_scripts_info->installed_urls); + installed_scripts_manager_params->manager_request = + installed_scripts_info->manager_request.PassMessagePipe(); + installed_scripts_manager_params->manager_host_ptr = + installed_scripts_info->manager_host_ptr.PassHandle(); + DCHECK(installed_scripts_manager_params->manager_request.is_valid()); + DCHECK(installed_scripts_manager_params->manager_host_ptr.is_valid()); } auto wrapper = std::make_unique<WorkerWrapper>( blink::WebEmbeddedWorker::Create( - std::move(context_client), std::move(manager), + std::move(context_client), + std::move(installed_scripts_manager_params), content_settings_proxy.PassInterface().PassHandle(), interface_provider.PassInterface().PassHandle()), params.worker_devtools_agent_route_id);
diff --git a/content/renderer/service_worker/thread_safe_script_container.cc b/content/renderer/service_worker/thread_safe_script_container.cc deleted file mode 100644 index 6f6e038..0000000 --- a/content/renderer/service_worker/thread_safe_script_container.cc +++ /dev/null
@@ -1,78 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/service_worker/thread_safe_script_container.h" - -#include "base/stl_util.h" - -namespace content { - -ThreadSafeScriptContainer::ThreadSafeScriptContainer() - : lock_(), waiting_cv_(&lock_), are_all_data_added_(false) {} - -void ThreadSafeScriptContainer::AddOnIOThread(const GURL& url, - std::unique_ptr<Data> data) { - base::AutoLock lock(lock_); - script_data_[url] = std::move(data); - if (url == waiting_url_) - waiting_cv_.Signal(); -} - -ThreadSafeScriptContainer::ScriptStatus -ThreadSafeScriptContainer::GetStatusOnWorkerThread(const GURL& url) { - base::AutoLock lock(lock_); - auto it = script_data_.find(url); - if (it == script_data_.end()) - return ScriptStatus::kPending; - if (!it->second) - return ScriptStatus::kTaken; - if (!it->second->IsValid()) - return ScriptStatus::kFailed; - return ScriptStatus::kReceived; -} - -void ThreadSafeScriptContainer::ResetOnWorkerThread(const GURL& url) { - base::AutoLock lock(lock_); - script_data_.erase(url); -} - -bool ThreadSafeScriptContainer::WaitOnWorkerThread(const GURL& url) { - base::AutoLock lock(lock_); - DCHECK(waiting_url_.is_empty()) - << "The script container is unexpectedly shared among worker threads."; - waiting_url_ = url; - while (script_data_.find(url) == script_data_.end()) { - // If waiting script hasn't been added yet though all data are received, - // that means something went wrong. - if (are_all_data_added_) { - waiting_url_ = GURL(); - return false; - } - // This is possible to be waken up spuriously, so that it's necessary to - // check if the entry is really added. - waiting_cv_.Wait(); - } - waiting_url_ = GURL(); - // TODO(shimazu): Keep the status for each entries instead of using IsValid(). - const auto& data = script_data_[url]; - return !data || data->IsValid(); -} - -std::unique_ptr<ThreadSafeScriptContainer::Data> -ThreadSafeScriptContainer::TakeOnWorkerThread(const GURL& url) { - base::AutoLock lock(lock_); - DCHECK(base::ContainsKey(script_data_, url)) - << "Script should be added before calling Take."; - return std::move(script_data_[url]); -} - -void ThreadSafeScriptContainer::OnAllDataAddedOnIOThread() { - base::AutoLock lock(lock_); - are_all_data_added_ = true; - waiting_cv_.Broadcast(); -} - -ThreadSafeScriptContainer::~ThreadSafeScriptContainer() = default; - -} // namespace content
diff --git a/content/renderer/service_worker/thread_safe_script_container.h b/content/renderer/service_worker/thread_safe_script_container.h deleted file mode 100644 index 037a072..0000000 --- a/content/renderer/service_worker/thread_safe_script_container.h +++ /dev/null
@@ -1,93 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <map> -#include <memory> - -#include "base/memory/ref_counted.h" -#include "base/synchronization/condition_variable.h" -#include "base/synchronization/lock.h" -#include "content/common/content_export.h" -#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h" - -#ifndef CONTENT_RENDERER_SERVICE_WORKER_THREAD_SAFE_SCRIPT_CONTAINER_H_ -#define CONTENT_RENDERER_SERVICE_WORKER_THREAD_SAFE_SCRIPT_CONTAINER_H_ - -namespace content { - -// ThreadSafeScriptContainer stores the scripts of a service worker for -// startup. This container is created for each service worker. The IO thread -// adds scripts to the container, and the worker thread takes the scripts. -// -// This class uses explicit synchronization because it needs to support -// synchronous importScripts() from the worker thread. -// -// This class is RefCounted because there is no ordering guarantee of lifetime -// of its owners, i.e. WebServiceWorkerInstalledScriptsManagerImpl and its -// Internal class. WebSWInstalledScriptsManagerImpl is destroyed earlier than -// Internal if the worker is terminated before all scripts are streamed, and -// Internal is destroyed earlier if all of scripts are received before finishing -// script evaluation. -class CONTENT_EXPORT ThreadSafeScriptContainer - : public base::RefCountedThreadSafe<ThreadSafeScriptContainer> { - public: - using Data = blink::WebServiceWorkerInstalledScriptsManager::RawScriptData; - - REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE(); - ThreadSafeScriptContainer(); - - enum class ScriptStatus { - // The script data has been received. - kReceived, - // The script data has been received but it has already been taken. - kTaken, - // Receiving the script has failed. - kFailed, - // The script data has not been received yet. - kPending - }; - - // Called on the IO thread. - void AddOnIOThread(const GURL& url, std::unique_ptr<Data> data); - - // Called on the worker thread. - ScriptStatus GetStatusOnWorkerThread(const GURL& url); - - // Removes the script. After calling this, ScriptStatus for the - // script will be kPending. - // Called on the worker thread. - void ResetOnWorkerThread(const GURL& url); - - // Waits until the script is added. The thread is blocked until the script is - // available or receiving the script fails. Returns false if an error happens - // and the waiting script won't be available forever. - // Called on the worker thread. - bool WaitOnWorkerThread(const GURL& url); - - // Called on the worker thread. - std::unique_ptr<Data> TakeOnWorkerThread(const GURL& url); - - // Called if no more data will be added. - // Called on the IO thread. - void OnAllDataAddedOnIOThread(); - - private: - friend class base::RefCountedThreadSafe<ThreadSafeScriptContainer>; - ~ThreadSafeScriptContainer(); - - // |lock_| protects |waiting_cv_|, |script_data_|, |waiting_url_| and - // |are_all_data_added_|. - base::Lock lock_; - // |waiting_cv_| is signaled when a script whose url matches to |waiting_url| - // is added, or OnAllDataAdded is called. The worker thread waits on this, and - // the IO thread signals it. - base::ConditionVariable waiting_cv_; - std::map<GURL, std::unique_ptr<Data>> script_data_; - GURL waiting_url_; - bool are_all_data_added_; -}; - -} // namespace content - -#endif // CONTENT_RENDERER_SERVICE_WORKER_THREAD_SAFE_SCRIPT_CONTAINER_H_
diff --git a/content/renderer/service_worker/thread_safe_script_container_unittest.cc b/content/renderer/service_worker/thread_safe_script_container_unittest.cc deleted file mode 100644 index a6853ed..0000000 --- a/content/renderer/service_worker/thread_safe_script_container_unittest.cc +++ /dev/null
@@ -1,226 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/service_worker/thread_safe_script_container.h" - -#include "base/bind.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace content { - -using ScriptStatus = ThreadSafeScriptContainer::ScriptStatus; - -class ThreadSafeScriptContainerTest : public testing::Test { - public: - ThreadSafeScriptContainerTest() - : writer_thread_("writer_thread"), - reader_thread_("reader_thread"), - writer_waiter_(base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED), - reader_waiter_(base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED), - container_(base::MakeRefCounted<ThreadSafeScriptContainer>()) {} - - protected: - void SetUp() override { - ASSERT_TRUE(writer_thread_.Start()); - ASSERT_TRUE(reader_thread_.Start()); - writer_task_runner_ = writer_thread_.task_runner(); - reader_task_runner_ = reader_thread_.task_runner(); - } - - void TearDown() override { - writer_thread_.Stop(); - reader_thread_.Stop(); - } - - base::WaitableEvent* AddOnWriterThread( - const GURL& url, - ThreadSafeScriptContainer::Data** out_data) { - writer_task_runner_->PostTask( - FROM_HERE, - base::BindOnce( - [](scoped_refptr<ThreadSafeScriptContainer> container, - const GURL& url, ThreadSafeScriptContainer::Data** out_data, - base::WaitableEvent* waiter) { - auto data = ThreadSafeScriptContainer::Data::Create( - blink::WebString::FromUTF8("utf-8") /* encoding */, - blink::WebVector<blink::WebVector<char>>() /* script_text */, - blink::WebVector<blink::WebVector<char>>() /* meta_data */); - *out_data = data.get(); - container->AddOnIOThread(url, std::move(data)); - waiter->Signal(); - }, - container_, url, out_data, &writer_waiter_)); - return &writer_waiter_; - } - - base::WaitableEvent* OnAllDataAddedOnWriterThread() { - writer_task_runner_->PostTask( - FROM_HERE, base::BindOnce( - [](scoped_refptr<ThreadSafeScriptContainer> container, - base::WaitableEvent* waiter) { - container->OnAllDataAddedOnIOThread(); - waiter->Signal(); - }, - container_, &writer_waiter_)); - return &writer_waiter_; - } - - base::WaitableEvent* GetStatusOnReaderThread(const GURL& url, - ScriptStatus* out_status) { - reader_task_runner_->PostTask( - FROM_HERE, base::BindOnce( - [](scoped_refptr<ThreadSafeScriptContainer> container, - const GURL& url, ScriptStatus* out_status, - base::WaitableEvent* waiter) { - *out_status = container->GetStatusOnWorkerThread(url); - waiter->Signal(); - }, - container_, url, out_status, &reader_waiter_)); - return &reader_waiter_; - } - - base::WaitableEvent* WaitOnReaderThread(const GURL& url, bool* out_exists) { - reader_task_runner_->PostTask( - FROM_HERE, - base::BindOnce( - [](scoped_refptr<ThreadSafeScriptContainer> container, - const GURL& url, bool* out_exists, base::WaitableEvent* waiter) { - *out_exists = container->WaitOnWorkerThread(url); - waiter->Signal(); - }, - container_, url, out_exists, &reader_waiter_)); - return &reader_waiter_; - } - - base::WaitableEvent* TakeOnReaderThread( - const GURL& url, - ThreadSafeScriptContainer::Data** out_data) { - reader_task_runner_->PostTask( - FROM_HERE, - base::BindOnce( - [](scoped_refptr<ThreadSafeScriptContainer> container, - const GURL& url, ThreadSafeScriptContainer::Data** out_data, - base::WaitableEvent* waiter) { - auto data = container->TakeOnWorkerThread(url); - *out_data = data.get(); - waiter->Signal(); - }, - container_, url, out_data, &reader_waiter_)); - return &reader_waiter_; - } - - private: - base::Thread writer_thread_; - base::Thread reader_thread_; - - scoped_refptr<base::SingleThreadTaskRunner> writer_task_runner_; - scoped_refptr<base::SingleThreadTaskRunner> reader_task_runner_; - - base::WaitableEvent writer_waiter_; - base::WaitableEvent reader_waiter_; - - scoped_refptr<ThreadSafeScriptContainer> container_; -}; - -TEST_F(ThreadSafeScriptContainerTest, WaitExistingKey) { - const GURL kKey("https://example.com/key"); - { - ScriptStatus result = ScriptStatus::kReceived; - GetStatusOnReaderThread(kKey, &result)->Wait(); - EXPECT_EQ(ScriptStatus::kPending, result); - } - - ThreadSafeScriptContainer::Data* added_data; - { - bool result = false; - base::WaitableEvent* pending_wait = WaitOnReaderThread(kKey, &result); - // This should not be signaled until data is added. - EXPECT_FALSE(pending_wait->IsSignaled()); - base::WaitableEvent* pending_write = AddOnWriterThread(kKey, &added_data); - pending_wait->Wait(); - pending_write->Wait(); - EXPECT_TRUE(result); - } - - { - ScriptStatus result = ScriptStatus::kFailed; - GetStatusOnReaderThread(kKey, &result)->Wait(); - EXPECT_EQ(ScriptStatus::kReceived, result); - } - - { - ThreadSafeScriptContainer::Data* taken_data; - TakeOnReaderThread(kKey, &taken_data)->Wait(); - EXPECT_EQ(added_data, taken_data); - } - - { - ScriptStatus result = ScriptStatus::kFailed; - GetStatusOnReaderThread(kKey, &result)->Wait(); - // The record of |kKey| should be exist though it's already taken. - EXPECT_EQ(ScriptStatus::kTaken, result); - } - - { - bool result = false; - WaitOnReaderThread(kKey, &result)->Wait(); - // Waiting for |kKey| should succeed. - EXPECT_TRUE(result); - - ThreadSafeScriptContainer::Data* taken_data; - TakeOnReaderThread(kKey, &taken_data)->Wait(); - // |taken_data| should be nullptr because it's already taken. - EXPECT_EQ(nullptr, taken_data); - } - - // Finish adding data. - OnAllDataAddedOnWriterThread()->Wait(); - - { - bool result = false; - WaitOnReaderThread(kKey, &result)->Wait(); - // The record has been already added, so Wait shouldn't fail. - EXPECT_TRUE(result); - - ThreadSafeScriptContainer::Data* taken_data; - TakeOnReaderThread(kKey, &taken_data)->Wait(); - // |taken_data| should be nullptr because it's already taken. - EXPECT_EQ(nullptr, taken_data); - } -} - -TEST_F(ThreadSafeScriptContainerTest, WaitNonExistingKey) { - const GURL kKey("https://example.com/key"); - { - ScriptStatus result = ScriptStatus::kReceived; - GetStatusOnReaderThread(kKey, &result)->Wait(); - EXPECT_EQ(ScriptStatus::kPending, result); - } - - { - bool result = true; - base::WaitableEvent* pending_wait = WaitOnReaderThread(kKey, &result); - // This should not be signaled until OnAllDataAdded is called. - EXPECT_FALSE(pending_wait->IsSignaled()); - base::WaitableEvent* pending_on_all_data_added = - OnAllDataAddedOnWriterThread(); - pending_wait->Wait(); - pending_on_all_data_added->Wait(); - // Aborted wait should return false. - EXPECT_FALSE(result); - } - - { - bool result = true; - WaitOnReaderThread(kKey, &result)->Wait(); - // Wait fails immediately because OnAllDataAdded is called. - EXPECT_FALSE(result); - } -} - -} // namespace content
diff --git a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.cc b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.cc deleted file mode 100644 index 157340b..0000000 --- a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.cc +++ /dev/null
@@ -1,298 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h" - -#include "base/barrier_closure.h" -#include "base/memory/ptr_util.h" -#include "base/stl_util.h" -#include "base/threading/thread_checker.h" -#include "mojo/public/cpp/bindings/strong_binding.h" - -namespace content { - -namespace { - -// Receiver is a class to read a Mojo data pipe. Received data are stored in -// chunks. Lives on the IO thread. Receiver is owned by Internal via -// BundledReceivers. It is created to read the script body or metadata from a -// data pipe, and is destroyed when the read finishes. -class Receiver { - public: - using BytesChunk = blink::WebVector<char>; - - Receiver(mojo::ScopedDataPipeConsumerHandle handle, uint64_t total_bytes) - : handle_(std::move(handle)), - watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL), - remaining_bytes_(total_bytes) {} - - void Start(base::OnceClosure callback) { - if (!handle_.is_valid()) { - std::move(callback).Run(); - return; - } - callback_ = std::move(callback); - // base::Unretained is safe because |watcher_| is owned by |this|. - MojoResult rv = watcher_.Watch( - handle_.get(), MOJO_HANDLE_SIGNAL_READABLE, - base::Bind(&Receiver::OnReadable, base::Unretained(this))); - DCHECK_EQ(MOJO_RESULT_OK, rv); - watcher_.ArmOrNotify(); - } - - void OnReadable(MojoResult) { - // It isn't necessary to handle MojoResult here since BeginReadDataRaw() - // returns an equivalent error. - const void* buffer = nullptr; - uint32_t bytes_read = 0; - MojoResult rv = - handle_->BeginReadData(&buffer, &bytes_read, MOJO_READ_DATA_FLAG_NONE); - switch (rv) { - case MOJO_RESULT_BUSY: - case MOJO_RESULT_INVALID_ARGUMENT: - NOTREACHED(); - return; - case MOJO_RESULT_FAILED_PRECONDITION: - // Closed by peer. - OnCompleted(); - return; - case MOJO_RESULT_SHOULD_WAIT: - watcher_.ArmOrNotify(); - return; - case MOJO_RESULT_OK: - break; - default: - // mojo::BeginReadDataRaw() should not return any other values. - // Notify the error to the browser by resetting the handle even though - // it's in the middle of data transfer. - OnCompleted(); - return; - } - - if (bytes_read > 0) - chunks_.emplace_back(static_cast<const char*>(buffer), bytes_read); - - rv = handle_->EndReadData(bytes_read); - DCHECK_EQ(rv, MOJO_RESULT_OK); - CHECK_GE(remaining_bytes_, bytes_read); - remaining_bytes_ -= bytes_read; - watcher_.ArmOrNotify(); - } - - bool is_running() const { return handle_.is_valid(); } - bool has_received_all_data() const { return remaining_bytes_ == 0; } - - blink::WebVector<BytesChunk> TakeChunks() { - DCHECK(!is_running()); - return blink::WebVector<BytesChunk>(std::move(chunks_)); - } - - private: - void OnCompleted() { - handle_.reset(); - watcher_.Cancel(); - if (!has_received_all_data()) - chunks_.clear(); - DCHECK(callback_); - std::move(callback_).Run(); - } - - base::OnceClosure callback_; - mojo::ScopedDataPipeConsumerHandle handle_; - mojo::SimpleWatcher watcher_; - - // std::vector is internally used because blink::WebVector is immutable and - // cannot append data. - std::vector<BytesChunk> chunks_; - uint64_t remaining_bytes_; -}; - -using RawScriptData = - blink::WebServiceWorkerInstalledScriptsManager::RawScriptData; - -// BundledReceivers is a helper class to wait for the end of reading body and -// meta data. Lives on the IO thread. -class BundledReceivers { - public: - BundledReceivers(mojo::ScopedDataPipeConsumerHandle meta_data_handle, - uint64_t meta_data_size, - mojo::ScopedDataPipeConsumerHandle body_handle, - uint64_t body_size) - : meta_data_(std::move(meta_data_handle), meta_data_size), - body_(std::move(body_handle), body_size) {} - - // Starts reading the pipes and invokes |callback| when both are finished. - void Start(base::OnceClosure callback) { - base::RepeatingClosure wait_all_closure = - base::BarrierClosure(2, std::move(callback)); - meta_data_.Start(wait_all_closure); - body_.Start(wait_all_closure); - } - - Receiver* meta_data() { return &meta_data_; } - Receiver* body() { return &body_; } - - private: - Receiver meta_data_; - Receiver body_; -}; - -// Internal lives on the IO thread. This receives -// blink::mojom::ServiceWorkerScriptInfo for all installed scripts and then -// starts reading the body and meta data from the browser. This instance will be -// kept alive as long as the Mojo's connection is established. -class Internal : public blink::mojom::ServiceWorkerInstalledScriptsManager { - public: - // Called on the IO thread. - // Creates and binds a new Internal instance to |request|. - static void Create( - scoped_refptr<ThreadSafeScriptContainer> script_container, - blink::mojom::ServiceWorkerInstalledScriptsManagerRequest request) { - mojo::MakeStrongBinding( - std::make_unique<Internal>(std::move(script_container)), - std::move(request)); - } - - Internal(scoped_refptr<ThreadSafeScriptContainer> script_container) - : script_container_(std::move(script_container)), weak_factory_(this) {} - - ~Internal() override { - DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_); - // Wake up a waiting thread so it does not wait forever. If the script has - // not been added yet, that means something went wrong. From here, - // script_container_->Wait() will return false if the script hasn't been - // added yet. - script_container_->OnAllDataAddedOnIOThread(); - } - - // Implements blink::mojom::ServiceWorkerInstalledScriptsManager. - // Called on the IO thread. - void TransferInstalledScript( - blink::mojom::ServiceWorkerScriptInfoPtr script_info) override { - DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_); - GURL script_url = script_info->script_url; - auto receivers = std::make_unique<BundledReceivers>( - std::move(script_info->meta_data), script_info->meta_data_size, - std::move(script_info->body), script_info->body_size); - receivers->Start(base::BindOnce(&Internal::OnScriptReceived, - weak_factory_.GetWeakPtr(), - base::Passed(&script_info))); - DCHECK(!base::ContainsKey(running_receivers_, script_url)); - running_receivers_[script_url] = std::move(receivers); - } - - // Called on the IO thread. - void OnScriptReceived(blink::mojom::ServiceWorkerScriptInfoPtr script_info) { - DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_); - const GURL& script_url = script_info->script_url; - auto iter = running_receivers_.find(script_url); - DCHECK(iter != running_receivers_.end()); - std::unique_ptr<BundledReceivers> receivers = std::move(iter->second); - DCHECK(receivers); - if (!receivers->body()->has_received_all_data() || - !receivers->meta_data()->has_received_all_data()) { - script_container_->AddOnIOThread(script_url, - RawScriptData::CreateInvalidInstance()); - running_receivers_.erase(iter); - return; - } - - auto script_data = RawScriptData::Create( - blink::WebString::FromUTF8(script_info->encoding), - receivers->body()->TakeChunks(), receivers->meta_data()->TakeChunks()); - for (const auto& entry : script_info->headers) { - script_data->AddHeader(blink::WebString::FromUTF8(entry.first), - blink::WebString::FromUTF8(entry.second)); - } - script_container_->AddOnIOThread(script_url, std::move(script_data)); - running_receivers_.erase(iter); - } - - private: - THREAD_CHECKER(io_thread_checker_); - std::map<GURL, std::unique_ptr<BundledReceivers>> running_receivers_; - scoped_refptr<ThreadSafeScriptContainer> script_container_; - base::WeakPtrFactory<Internal> weak_factory_; -}; - -} // namespace - -// static -std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManager> -WebServiceWorkerInstalledScriptsManagerImpl::Create( - blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info, - scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) { - auto script_container = base::MakeRefCounted<ThreadSafeScriptContainer>(); - blink::mojom::ServiceWorkerInstalledScriptsManagerHostPtr manager_host_ptr( - std::move(installed_scripts_info->manager_host_ptr)); - std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManager> manager = - base::WrapUnique<WebServiceWorkerInstalledScriptsManagerImpl>( - new WebServiceWorkerInstalledScriptsManagerImpl( - std::move(installed_scripts_info->installed_urls), - script_container, std::move(manager_host_ptr))); - io_task_runner->PostTask( - FROM_HERE, - base::BindOnce(&Internal::Create, script_container, - std::move(installed_scripts_info->manager_request))); - return manager; -} - -WebServiceWorkerInstalledScriptsManagerImpl:: - WebServiceWorkerInstalledScriptsManagerImpl( - std::vector<GURL>&& installed_urls, - scoped_refptr<ThreadSafeScriptContainer> script_container, - blink::mojom::ServiceWorkerInstalledScriptsManagerHostPtr manager_host) - : installed_urls_(installed_urls.begin(), installed_urls.end()), - script_container_(std::move(script_container)), - manager_host_( - blink::mojom::ThreadSafeServiceWorkerInstalledScriptsManagerHostPtr:: - Create(std::move(manager_host))) {} - -WebServiceWorkerInstalledScriptsManagerImpl:: - ~WebServiceWorkerInstalledScriptsManagerImpl() = default; - -bool WebServiceWorkerInstalledScriptsManagerImpl::IsScriptInstalled( - const blink::WebURL& script_url) const { - return base::ContainsKey(installed_urls_, script_url); -} - -std::unique_ptr<RawScriptData> -WebServiceWorkerInstalledScriptsManagerImpl::GetRawScriptData( - const blink::WebURL& script_url) { - TRACE_EVENT1("ServiceWorker", - "WebServiceWorkerInstalledScriptsManagerImpl::GetRawScriptData", - "script_url", script_url.GetString().Utf8()); - if (!IsScriptInstalled(script_url)) - return nullptr; - - ThreadSafeScriptContainer::ScriptStatus status = - script_container_->GetStatusOnWorkerThread(script_url); - // If the script has already been taken, request the browser to send the - // script. - if (status == ThreadSafeScriptContainer::ScriptStatus::kTaken) { - script_container_->ResetOnWorkerThread(script_url); - (*manager_host_)->RequestInstalledScript(script_url); - status = script_container_->GetStatusOnWorkerThread(script_url); - } - - // If the script has not been received at this point, wait for arrival by - // blocking the worker thread. - if (status == ThreadSafeScriptContainer::ScriptStatus::kPending) { - // Wait for arrival of the script. - const bool success = script_container_->WaitOnWorkerThread(script_url); - // It can fail due to an error on Mojo pipes. - if (!success) - return RawScriptData::CreateInvalidInstance(); - status = script_container_->GetStatusOnWorkerThread(script_url); - DCHECK_NE(ThreadSafeScriptContainer::ScriptStatus::kPending, status); - } - - if (status == ThreadSafeScriptContainer::ScriptStatus::kFailed) - return RawScriptData::CreateInvalidInstance(); - DCHECK_EQ(ThreadSafeScriptContainer::ScriptStatus::kReceived, status); - - return script_container_->TakeOnWorkerThread(script_url); -} - -} // namespace content
diff --git a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h b/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h deleted file mode 100644 index 9df608af..0000000 --- a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_SERVICE_WORKER_WEB_SERVICE_WORKER_INSTALLED_SCRIPTS_MANAGER_IMPL_H_ -#define CONTENT_RENDERER_SERVICE_WORKER_WEB_SERVICE_WORKER_INSTALLED_SCRIPTS_MANAGER_IMPL_H_ - -#include <set> -#include <vector> - -#include "content/renderer/service_worker/thread_safe_script_container.h" -#include "third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom.h" -#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h" - -namespace content { - -class CONTENT_EXPORT WebServiceWorkerInstalledScriptsManagerImpl final - : public blink::WebServiceWorkerInstalledScriptsManager { - public: - // Called on the main thread. - static std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManager> Create( - blink::mojom::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info, - scoped_refptr<base::SingleThreadTaskRunner> io_task_runner); - - ~WebServiceWorkerInstalledScriptsManagerImpl() override; - - // WebServiceWorkerInstalledScriptsManager implementation. - bool IsScriptInstalled(const blink::WebURL& script_url) const override; - std::unique_ptr<RawScriptData> GetRawScriptData( - const blink::WebURL& script_url) override; - - private: - WebServiceWorkerInstalledScriptsManagerImpl( - std::vector<GURL>&& installed_urls, - scoped_refptr<ThreadSafeScriptContainer> script_container, - blink::mojom::ServiceWorkerInstalledScriptsManagerHostPtr manager_host); - - const std::set<GURL> installed_urls_; - scoped_refptr<ThreadSafeScriptContainer> script_container_; - - scoped_refptr< - blink::mojom::ThreadSafeServiceWorkerInstalledScriptsManagerHostPtr> - manager_host_; -}; - -} // namespace content - -#endif // CONTENT_RENDERER_SERVICE_WORKER_WEB_SERVICE_WORKER_INSTALLED_SCRIPTS_MANAGER_IMPL_H_
diff --git a/content/shell/browser/shell_views.cc b/content/shell/browser/shell_views.cc index 352f312..720310f 100644 --- a/content/shell/browser/shell_views.cc +++ b/content/shell/browser/shell_views.cc
@@ -77,7 +77,7 @@ url_entry_->SetText(base::ASCIIToUTF16(url.spec())); } void SetWebContents(WebContents* web_contents, const gfx::Size& size) { - contents_view_->SetLayoutManager(new views::FillLayout()); + contents_view_->SetLayoutManager(std::make_unique<views::FillLayout>()); web_view_ = new views::WebView(web_contents->GetBrowserContext()); web_view_->SetWebContents(web_contents); web_view_->SetPreferredSize(size); @@ -116,7 +116,8 @@ void InitShellWindow() { SetBackground(views::CreateStandardPanelBackground()); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); views::ColumnSet* column_set = layout->AddColumnSet(0); if (!shell_->hide_toolbar()) @@ -130,8 +131,8 @@ if (!shell_->hide_toolbar()) { layout->AddPaddingRow(0, 2); layout->StartRow(0, 0); - views::GridLayout* toolbar_layout = - views::GridLayout::CreateAndInstall(toolbar_view_); + views::GridLayout* toolbar_layout = toolbar_view_->SetLayoutManager( + std::make_unique<views::GridLayout>(toolbar_view_)); views::ColumnSet* toolbar_column_set = toolbar_layout->AddColumnSet(0);
diff --git a/content/shell/test_runner/test_plugin.cc b/content/shell/test_runner/test_plugin.cc index a19b7b1e..c0556f3 100644 --- a/content/shell/test_runner/test_plugin.cc +++ b/content/shell/test_runner/test_plugin.cc
@@ -264,10 +264,8 @@ gl_->GenMailboxCHROMIUM(mailbox_.name); gl_->ProduceTextureDirectCHROMIUM(color_texture_, mailbox_.name); - const GLuint64 fence_sync = gl_->InsertFenceSyncCHROMIUM(); gl_->Flush(); - - gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token_.GetData()); + gl_->GenSyncTokenCHROMIUM(sync_token_.GetData()); shared_bitmap_ = nullptr; } else {
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 96e3bfd..124a147 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1346,6 +1346,7 @@ "../browser/renderer_host/compositor_resize_lock_unittest.cc", "../browser/renderer_host/cursor_manager_unittest.cc", "../browser/renderer_host/dwrite_font_proxy_message_filter_win_unittest.cc", + "../browser/renderer_host/input/fling_controller_unittest.cc", "../browser/renderer_host/input/gesture_event_queue_unittest.cc", "../browser/renderer_host/input/input_router_impl_unittest.cc", "../browser/renderer_host/input/legacy_input_router_impl_unittest.cc", @@ -1587,8 +1588,6 @@ "../renderer/service_worker/service_worker_provider_context_unittest.cc", "../renderer/service_worker/service_worker_subresource_loader_unittest.cc", "../renderer/service_worker/service_worker_timeout_timer_unittest.cc", - "../renderer/service_worker/thread_safe_script_container_unittest.cc", - "../renderer/service_worker/web_service_worker_installed_scripts_manager_impl_unittest.cc", "../renderer/skia_benchmarking_extension_unittest.cc", "../renderer/v8_value_converter_impl_unittest.cc", "../renderer/worker_thread_registry_unittest.cc",
diff --git a/content/test/gpu/generate_buildbot_json.py b/content/test/gpu/generate_buildbot_json.py index 9a5dcdbd..aa1af78 100755 --- a/content/test/gpu/generate_buildbot_json.py +++ b/content/test/gpu/generate_buildbot_json.py
@@ -260,6 +260,8 @@ 'GPU Linux Builder (dbg)' : {}, 'GPU Linux Ozone Builder' : {}, 'GPU Linux dEQP Builder' : {}, + 'GPU Android arm Builder' : {}, + 'GPU Android arm64 Builder' : {}, }, 'testers': { @@ -389,17 +391,15 @@ 'swarming': False, 'os_type': 'win', }, - 'Win10 Release (NVIDIA Quadro P400)': { + 'Win10 Release Swarmed (Intel HD 630)': { 'swarming_dimensions': [ { - 'gpu': '10de:1cb3', - 'os': 'Windows-10' + 'gpu': '8086:5912', + 'os': 'Windows-10', }, ], 'build_config': 'Release', - # This bot is a one-off and doesn't have similar slaves in the - # swarming pool. - 'swarming': False, + 'swarming': True, 'os_type': 'win', }, 'Win7 x64 Release (NVIDIA)': { @@ -675,6 +675,17 @@ 'swarming': False, 'os_type': 'linux', }, + 'Linux Release Swarmed (Intel HD 630)': { + 'swarming_dimensions': [ + { + 'gpu': '8086:5912', + 'os': 'Ubuntu' + }, + ], + 'build_config': 'Release', + 'swarming': True, + 'os_type': 'linux', + }, 'Linux Release (AMD R7 240)': { 'swarming_dimensions': [ {
diff --git a/content/test/gpu/gpu_tests/gpu_process_expectations.py b/content/test/gpu/gpu_tests/gpu_process_expectations.py index 16b5bac7..50a2e0c 100644 --- a/content/test/gpu/gpu_tests/gpu_process_expectations.py +++ b/content/test/gpu/gpu_tests/gpu_process_expectations.py
@@ -42,3 +42,7 @@ # Seems to have become flaky on Windows recently. self.Flaky('GpuProcess_only_one_workaround', ['win'], bug=700522) + + # TODO(zmo): Enable this test once about:gpu status reporting is wired + # with GpuFeatureInfo from GPU process. + self.Fail('GpuProcess_readback_webgl_gpu_process', ['linux'])
diff --git a/content/test/gpu/gpu_tests/maps_integration_test.py b/content/test/gpu/gpu_tests/maps_integration_test.py index 2692d93..f5cc8566 100644 --- a/content/test/gpu/gpu_tests/maps_integration_test.py +++ b/content/test/gpu/gpu_tests/maps_integration_test.py
@@ -14,8 +14,8 @@ from py_utils import cloud_storage -wpr_path = os.path.join(path_util.GetChromiumSrcDir(), - 'tools', 'perf', 'page_sets', 'data') +maps_perf_test_path = os.path.join( + path_util.GetChromiumSrcDir(), 'tools', 'perf', 'page_sets', 'maps_perf_test') data_path = os.path.join(path_util.GetChromiumSrcDir(), 'content', 'test', 'gpu', 'gpu_tests') @@ -47,8 +47,10 @@ '--force-color-profile=srgb', '--ensure-forced-color-profile'] cls.CustomizeBrowserArgs(browser_args) - cls.StartWPRServer(os.path.join(wpr_path, 'maps_005.wprgo'), - cloud_storage.PUBLIC_BUCKET) + cloud_storage.GetIfChanged( + os.path.join(maps_perf_test_path, 'load_dataset'), + cloud_storage.PUBLIC_BUCKET) + cls.SetStaticServerDirs([maps_perf_test_path]) cls.StartBrowser() @classmethod @@ -60,7 +62,7 @@ def GenerateGpuTests(cls, options): cls.SetParsedCommandLineOptions(options) yield('Maps_maps', - 'http://map-test/performance.html', + 'file://performance.html', ('maps_pixel_expectations.json')) def _ReadPixelExpectations(self, expectations_file): @@ -92,8 +94,9 @@ pixel_expectations_file = args[0] action_runner = tab.action_runner action_runner.Navigate(url) - action_runner.WaitForJavaScriptCondition( - 'window.testDone', timeout=320) + action_runner.WaitForJavaScriptCondition('window.startTest != undefined') + action_runner.EvaluateJavaScript('window.startTest()') + action_runner.WaitForJavaScriptCondition('window.testDone', timeout=320) # TODO(kbr): This should not be necessary, but it's not clear if the test # is failing on the bots in its absence. Remove once we can verify that
diff --git a/content/test/gpu/gpu_tests/maps_pixel_expectations.json b/content/test/gpu/gpu_tests/maps_pixel_expectations.json index d656fc6..396ff95 100644 --- a/content/test/gpu/gpu_tests/maps_pixel_expectations.json +++ b/content/test/gpu/gpu_tests/maps_pixel_expectations.json
@@ -31,37 +31,37 @@ }, { "comment": "light green", - "location": [ 100, 175 ], + "location": [ 43, 247 ], "size": [ 1, 1 ], - "color": [ 202, 223, 170 ], + "color": [ 214, 232, 186 ], "tolerance": 3 }, { "comment": "darker green", - "location": [ 40, 250 ], + "location": [ 326, 111 ], "size": [ 1, 1 ], - "color": [ 190, 214, 190 ], + "color": [ 203, 230, 163 ], "tolerance": 3 }, { "comment": "blue lake", - "location": [ 590, 390 ], + "location": [ 593, 393 ], "size": [ 1, 1 ], - "color": [ 145, 188, 255 ], + "color": [ 163, 205, 255 ], "tolerance": 3 }, { - "comment": "darker gray", - "location": [ 90, 125 ], + "comment": "gray", + "location": [ 95, 117 ], "size": [ 1, 1 ], - "color": [ 233, 229, 220 ], + "color": [ 232, 232, 232 ], "tolerance": 3 }, { - "comment": "lighter gray", - "location": [ 390, 300 ], + "comment": "tan", + "location": [ 344, 263 ], "size": [ 1, 1 ], - "color": [ 240, 237, 229 ], + "color": [ 240, 237, 230 ], "tolerance": 3 } ]
diff --git a/content/test/web_gesture_curve_mock.cc b/content/test/web_gesture_curve_mock.cc index cd68a605..977c02c 100644 --- a/content/test/web_gesture_curve_mock.cc +++ b/content/test/web_gesture_curve_mock.cc
@@ -16,15 +16,14 @@ WebGestureCurveMock::~WebGestureCurveMock() { } -bool WebGestureCurveMock::Apply(double time, - blink::WebGestureCurveTarget* target) { +bool WebGestureCurveMock::Advance(double time, + gfx::Vector2dF& out_current_velocity, + gfx::Vector2dF& out_delta_to_scroll) { blink::WebSize displacement(velocity_.x * time, velocity_.y * time); - blink::WebFloatSize increment(displacement.width - cumulative_scroll_.width, - displacement.height - cumulative_scroll_.height); + out_delta_to_scroll = + gfx::Vector2dF(displacement.width - cumulative_scroll_.width, + displacement.height - cumulative_scroll_.height); cumulative_scroll_ = displacement; - blink::WebFloatSize velocity(velocity_.x, velocity_.y); - // scrollBy() could delete this curve if the animation is over, so don't - // touch any member variables after making that call. - target->ScrollBy(increment, velocity); + out_current_velocity = gfx::Vector2dF(velocity_.x, velocity_.y); return true; }
diff --git a/content/test/web_gesture_curve_mock.h b/content/test/web_gesture_curve_mock.h index ef61a1ce..2cc2fe7 100644 --- a/content/test/web_gesture_curve_mock.h +++ b/content/test/web_gesture_curve_mock.h
@@ -20,8 +20,10 @@ const blink::WebSize& cumulative_scroll); ~WebGestureCurveMock() override; - // Returns false if curve has finished and can no longer be applied. - bool Apply(double time, blink::WebGestureCurveTarget* target) override; + // Returns false if curve has finished and can no longer advance. + bool Advance(double time, + gfx::Vector2dF& out_current_velocity, + gfx::Vector2dF& out_delta_to_scroll) override; private: blink::WebFloatPoint velocity_;
diff --git a/device/geolocation/geolocation_context.cc b/device/geolocation/geolocation_context.cc index 0629ff2..878d0c83 100644 --- a/device/geolocation/geolocation_context.cc +++ b/device/geolocation/geolocation_context.cc
@@ -48,6 +48,7 @@ } void GeolocationContext::ClearOverride() { + geoposition_override_.reset(); for (auto& impl : impls_) { impl->ClearOverride(); }
diff --git a/device/geolocation/geolocation_provider.h b/device/geolocation/geolocation_provider.h index ba23762f..385736d 100644 --- a/device/geolocation/geolocation_provider.h +++ b/device/geolocation/geolocation_provider.h
@@ -23,8 +23,13 @@ // must communicate with it on the same thread. // The underlying location arbitrator will only be enabled whilst there is at // least one registered observer or pending callback (and only after -// UserDidOptIntoLocationServices). The arbitrator and the location providers it -// uses run on a separate Geolocation thread. +// mojom::UserDidOptIntoLocationServices() which is implemented by +// GeolocationProviderImpl). The arbitrator and the location providers it uses +// run on a separate Geolocation thread. +// TODO(ke.he@intel.com): With the proceeding of the servicification of +// geolocation, the geolocation core will be moved into //services/device and as +// a internal part of Device Service. This geolocation_provider.h will also be +// removed. class GeolocationProvider { public: DEVICE_GEOLOCATION_EXPORT static GeolocationProvider* GetInstance(); @@ -56,12 +61,6 @@ const LocationUpdateCallback& callback, bool enable_high_accuracy) = 0; - // Calling this method indicates the user has opted into using location - // services, including sending network requests to [Google servers to] resolve - // the user's location. Use this method carefully, in line with the rules in - // go/chrome-privacy-doc. - virtual void UserDidOptIntoLocationServices() = 0; - virtual bool HighAccuracyLocationInUse() = 0; // Overrides the current location for testing.
diff --git a/device/geolocation/geolocation_provider_impl.cc b/device/geolocation/geolocation_provider_impl.cc index 50a38b7..9d9a4b5 100644 --- a/device/geolocation/geolocation_provider_impl.cc +++ b/device/geolocation/geolocation_provider_impl.cc
@@ -72,14 +72,6 @@ return subscription; } -void GeolocationProviderImpl::UserDidOptIntoLocationServices() { - DCHECK(main_task_runner_->BelongsToCurrentThread()); - bool was_permission_granted = user_did_opt_into_location_services_; - user_did_opt_into_location_services_ = true; - if (IsRunning() && !was_permission_granted) - InformProvidersPermissionGranted(); -} - bool GeolocationProviderImpl::HighAccuracyLocationInUse() { return !high_accuracy_callbacks_.empty(); } @@ -108,11 +100,29 @@ return base::Singleton<GeolocationProviderImpl>::get(); } +void GeolocationProviderImpl::BindGeolocationControlRequest( + mojom::GeolocationControlRequest request) { + // The |binding_| has been bound already here means that more than one + // GeolocationPermissionContext in chrome tried to bind to Device Service. + // We only bind the first request. See more info in geolocation_control.mojom. + if (!binding_.is_bound()) + binding_.Bind(std::move(request)); +} + +void GeolocationProviderImpl::UserDidOptIntoLocationServices() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + bool was_permission_granted = user_did_opt_into_location_services_; + user_did_opt_into_location_services_ = true; + if (IsRunning() && !was_permission_granted) + InformProvidersPermissionGranted(); +} + GeolocationProviderImpl::GeolocationProviderImpl() : base::Thread("Geolocation"), user_did_opt_into_location_services_(false), ignore_location_updates_(false), - main_task_runner_(base::ThreadTaskRunnerHandle::Get()) { + main_task_runner_(base::ThreadTaskRunnerHandle::Get()), + binding_(this) { DCHECK(main_task_runner_->BelongsToCurrentThread()); high_accuracy_callbacks_.set_removal_callback(base::Bind( &GeolocationProviderImpl::OnClientsChanged, base::Unretained(this)));
diff --git a/device/geolocation/geolocation_provider_impl.h b/device/geolocation/geolocation_provider_impl.h index 24631bdf..c85d494 100644 --- a/device/geolocation/geolocation_provider_impl.h +++ b/device/geolocation/geolocation_provider_impl.h
@@ -16,7 +16,9 @@ #include "device/geolocation/geolocation_export.h" #include "device/geolocation/geolocation_provider.h" #include "device/geolocation/public/cpp/location_provider.h" +#include "device/geolocation/public/interfaces/geolocation_control.mojom.h" #include "device/geolocation/public/interfaces/geoposition.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" namespace base { template <typename Type> @@ -33,13 +35,13 @@ class DEVICE_GEOLOCATION_EXPORT GeolocationProviderImpl : public GeolocationProvider, + public mojom::GeolocationControl, public base::Thread { public: // GeolocationProvider implementation: std::unique_ptr<GeolocationProvider::Subscription> AddLocationUpdateCallback( const LocationUpdateCallback& callback, bool enable_high_accuracy) override; - void UserDidOptIntoLocationServices() override; bool HighAccuracyLocationInUse() override; void OverrideLocationForTesting(const mojom::Geoposition& position) override; @@ -59,6 +61,11 @@ static void SetCustomLocationProviderCallback( const CustomLocationProviderCallback& callback); + void BindGeolocationControlRequest(mojom::GeolocationControlRequest request); + + // mojom::GeolocationControl implementation: + void UserDidOptIntoLocationServices() override; + bool user_did_opt_into_location_services_for_testing() { return user_did_opt_into_location_services_; } @@ -111,6 +118,8 @@ // Only to be used on the geolocation thread. std::unique_ptr<LocationProvider> arbitrator_; + mojo::Binding<mojom::GeolocationControl> binding_; + DISALLOW_COPY_AND_ASSIGN(GeolocationProviderImpl); };
diff --git a/device/geolocation/public/interfaces/BUILD.gn b/device/geolocation/public/interfaces/BUILD.gn index cb53b6d..e616478 100644 --- a/device/geolocation/public/interfaces/BUILD.gn +++ b/device/geolocation/public/interfaces/BUILD.gn
@@ -9,6 +9,7 @@ "geolocation.mojom", "geolocation_config.mojom", "geolocation_context.mojom", + "geolocation_control.mojom", "geoposition.mojom", ] public_deps = [
diff --git a/device/geolocation/public/interfaces/geolocation_control.mojom b/device/geolocation/public/interfaces/geolocation_control.mojom new file mode 100644 index 0000000..0b209fb --- /dev/null +++ b/device/geolocation/public/interfaces/geolocation_control.mojom
@@ -0,0 +1,24 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module device.mojom; + +// GeolocationControl manages Geolocation's permission model. In particular, +// before geolocation can be accessed by any client, a trusted client must +// connect to GeolocationControl to inform the geolocation implementation that +// the user has opted into location services. It is assumed that before making +// this connection, that trusted client has interacted with the user to obtain +// this permission. Note that as the Device Service is a global service, this +// permission is also granted globally once it is granted at all. If a +// finer-granularity permission model is desired in a specific context, it is up +// to the client of the Device Service to manage that permission model (for +// example, the chrome_browser trusted client manages the web's per-origin +// permission model). +interface GeolocationControl { + // Calling this method indicates the user has opted into using location + // services, including sending network requests to [Google servers to] resolve + // the user's location. Use this method carefully, in line with the rules in + // go/chrome-privacy-doc. + UserDidOptIntoLocationServices(); +};
diff --git a/device/vr/openvr/test/DEPS b/device/vr/openvr/test/DEPS index c662c25..fe76a61 100644 --- a/device/vr/openvr/test/DEPS +++ b/device/vr/openvr/test/DEPS
@@ -1,3 +1,3 @@ -include_rules = [ - "+third_party/openvr/src", -] +include_rules = [ + "+third_party/openvr/src", +]
diff --git a/docs/design/gpu_synchronization.md b/docs/design/gpu_synchronization.md index 9bd079e2..ae2e695 100644 --- a/docs/design/gpu_synchronization.md +++ b/docs/design/gpu_synchronization.md
@@ -119,12 +119,13 @@ using explicit synchronization, but it doesn't do that today.) See also the "CHROMIUM fence sync" section below. -## Command buffer GL clients: use CHROMIUM fence sync +## Command buffer GL clients: use CHROMIUM sync tokens Chrome's command buffer IPC interface uses multiple layers. There are multiple active IPC channels (typically one per process, i.e. one per Renderer and one -for Browser). Each IPC channel has multiple streams, and each stream can contain -multiple command buffers, which in turn contain a sequence of GL commands. +for Browser). Each IPC channel has multiple scheduling groups (also called +streams), and each stream can contain multiple command buffers, which in turn +contain a sequence of GL commands. Command buffers in the same client-side share group must be in the same stream. Command scheduling granuarity is at the stream level, and a client can choose to @@ -133,14 +134,13 @@ [ui::ContextProviderCommandBuffer](/src/services/ui/public/cpp/gpu/context_provider_command_buffer.h) constructor. -The CHROMIUM fence sync mechanism is intended to order operations among -command buffer GL instructions. It is based on creating a fence sync object in the -stream, flushing it appropriately (see below), and generating a sync token from -it which is a cross-context transportable reference to the underlying fence -sync. A WaitSyncTokenCHROMIUM call does **not** ensure that the underlying GL -commands have been executed at the GPU driver level, this mechanism is not -suitable for synchronizing command buffer GL operations with a local -driver-level GL context. +The CHROMIUM sync token is intended to order operations among command buffer GL +instructions. It inserts an internal fence sync command in the stream, flushing +it appropriately (see below), and generating a sync token from it which is a +cross-context transportable reference to the underlying fence sync. A +WaitSyncTokenCHROMIUM call does **not** ensure that the underlying GL commands +have been executed at the GPU driver level, this mechanism is not suitable for +synchronizing command buffer GL operations with a local driver-level GL context. See the [CHROMIUM_sync_point](/src/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_sync_point.txt) @@ -166,9 +166,7 @@ ```c++ // stream A Render1(glA); -uint64 fence = glA->InsertFenceSyncCHROMIUM(); -glA->OrderingBarrierCHROMIUM(); -glA->GenUnverifiedSyncTokenCHROMIUM(fence, out_sync_token); +glA->GenUnverifiedSyncTokenCHROMIUM(out_sync_token); // stream B glB->WaitSyncTokenCHROMIUM(); @@ -184,8 +182,7 @@ ```c++ // IPC channel in process X Render1(glX); -uint64 fence = glX->InsertFenceSyncCHROMIUM(); -glX->GenSyncTokenCHROMIUM(fence, out_sync_token); +glX->GenSyncTokenCHROMIUM(out_sync_token); // IPC channel in process Y glY->WaitSyncTokenCHROMIUM(); @@ -197,12 +194,8 @@ necessary. Use this to avoid multiple sequential flushes: ```c++ -uint64 fence1 = gl->InsertFenceSyncCHROMIUM(); -gl->OrderingBarrierCHROMIUM(); -gl->GenUnverifiedSyncTokenCHROMIUM(fence1, out_sync_tokens[0]); -uint64 fence2 = gl->InsertFenceSyncCHROMIUM(); -gl->OrderingBarrierCHROMIUM(); -gl->GenUnverifiedSyncTokenCHROMIUM(fence2, out_sync_tokens[1]); +gl->GenUnverifiedSyncTokenCHROMIUM(out_sync_tokens[0]); +gl->GenUnverifiedSyncTokenCHROMIUM(out_sync_tokens[1]); gl->VerifySyncTokensCHROMIUM(out_sync_tokens, 2); ```
diff --git a/docs/linux_build_instructions.md b/docs/linux_build_instructions.md index 840e84ff..1e08792e 100644 --- a/docs/linux_build_instructions.md +++ b/docs/linux_build_instructions.md
@@ -329,8 +329,7 @@ ```shell $ sudo pacman -S --needed python perl gcc gcc-libs bison flex gperf pkgconfig \ -nss alsa-lib gconf glib2 gtk2 nspr ttf-ms-fonts freetype2 cairo dbus \ -libgnome-keyring +nss alsa-lib glib2 gtk2 nspr ttf-ms-fonts freetype2 cairo dbus libgnome-keyring ``` For the optional packages on Arch Linux: @@ -379,13 +378,13 @@ su -c 'yum install git python bzip2 tar pkgconfig atk-devel alsa-lib-devel \ bison binutils brlapi-devel bluez-libs-devel bzip2-devel cairo-devel \ cups-devel dbus-devel dbus-glib-devel expat-devel fontconfig-devel \ -freetype-devel gcc-c++ GConf2-devel glib2-devel glibc.i686 gperf \ -glib2-devel gtk2-devel gtk3-devel java-1.*.0-openjdk-devel libatomic \ -libcap-devel libffi-devel libgcc.i686 libgnome-keyring-devel libjpeg-devel \ -libstdc++.i686 libX11-devel libXScrnSaver-devel libXtst-devel \ -libxkbcommon-x11-devel ncurses-compat-libs nspr-devel nss-devel pam-devel \ -pango-devel pciutils-devel pulseaudio-libs-devel zlib.i686 httpd mod_ssl \ -php php-cli python-psutil wdiff xorg-x11-server-Xvfb' +freetype-devel gcc-c++ glib2-devel glibc.i686 gperf glib2-devel gtk2-devel \ +gtk3-devel java-1.*.0-openjdk-devel libatomic libcap-devel libffi-devel \ +libgcc.i686 libgnome-keyring-devel libjpeg-devel libstdc++.i686 libX11-devel \ +libXScrnSaver-devel libXtst-devel libxkbcommon-x11-devel ncurses-compat-libs \ +nspr-devel nss-devel pam-devel pango-devel pciutils-devel \ +pulseaudio-libs-devel zlib.i686 httpd mod_ssl php php-cli python-psutil wdiff \ +xorg-x11-server-Xvfb' ``` The fonts needed by Blink's LayoutTests can be obtained by following [these @@ -405,14 +404,14 @@ ```shell urpmi lib64fontconfig-devel lib64alsa2-devel lib64dbus-1-devel \ -lib64GConf2-devel lib64freetype6-devel lib64atk1.0-devel lib64gtk+2.0_0-devel \ +lib64freetype6-devel lib64atk1.0-devel lib64gtk+2.0_0-devel \ lib64pango1.0-devel lib64cairo-devel lib64nss-devel lib64nspr-devel g++ python \ perl bison flex subversion gperf ``` * `msttcorefonts` are not available, you will need to build your own (see instructions, not hard to do, see - [mandriva_msttcorefonts.md](mandriva_msttcorefonts.md)) or use `drakfont` to + [mandriva\_msttcorefonts.md](mandriva_msttcorefonts.md)) or use `drakfont` to import the fonts from a Windows installation. ### OpenSUSE @@ -422,10 +421,9 @@ (openSUSE 11.1 and higher) ```shell -sudo zypper in subversion pkg-config python perl \ - bison flex gperf mozilla-nss-devel glib2-devel gtk-devel \ - wdiff lighttpd gcc gcc-c++ gconf2-devel mozilla-nspr \ - mozilla-nspr-devel php5-fastcgi alsa-devel libexpat-devel \ +sudo zypper in subversion pkg-config python perl bison flex gperf \ + mozilla-nss-devel glib2-devel gtk-devel wdiff lighttpd gcc gcc-c++ \ + mozilla-nspr mozilla-nspr-devel php5-fastcgi alsa-devel libexpat-devel \ libjpeg-devel libbz2-devel ``` @@ -439,7 +437,7 @@ sudo zypper in subversion pkg-config python perl \ bison flex gperf mozilla-nss-devel glib2-devel gtk-devel \ libnspr4-0d libnspr4-dev wdiff lighttpd gcc gcc-c++ libexpat-devel \ - php5-cgi gconf2-devel alsa-devel gtk2-devel jpeg-devel + php5-cgi alsa-devel gtk2-devel jpeg-devel ``` The Ubuntu package `sun-java6-fonts` contains a subset of Java of the fonts used.
diff --git a/extensions/browser/api/media_perception_private/media_perception_api_manager.cc b/extensions/browser/api/media_perception_private/media_perception_api_manager.cc index 359b63d..7ea97079 100644 --- a/extensions/browser/api/media_perception_private/media_perception_api_manager.cc +++ b/extensions/browser/api/media_perception_private/media_perception_api_manager.cc
@@ -4,6 +4,7 @@ #include "extensions/browser/api/media_perception_private/media_perception_api_manager.h" +#include "base/files/file_path.h" #include "base/lazy_instance.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/media_analytics_client.h" @@ -35,13 +36,21 @@ return diagnostics; } -media_perception::ComponentState GetComponentStateForComponentStatus( - const media_perception::ComponentStatus status) { +media_perception::ComponentState GetFailedToInstallComponentState() { media_perception::ComponentState component_state; - component_state.status = status; + component_state.status = media_perception::COMPONENT_STATUS_FAILED_TO_INSTALL; return component_state; } +// Pulls out the version number from a mount_point location for the media +// perception component. Mount points look like +// /run/imageloader/rtanalytics-light/1.0, where 1.0 is the version string. +std::unique_ptr<std::string> ExtractVersionFromMountPoint( + const std::string& mount_point) { + return std::make_unique<std::string>( + base::FilePath(mount_point).BaseName().value()); +} + } // namespace // static @@ -109,8 +118,7 @@ APISetAnalyticsComponentCallback callback) { if (analytics_process_state_ != AnalyticsProcessState::IDLE) { LOG(WARNING) << "Analytics process is not STOPPED."; - std::move(callback).Run(GetComponentStateForComponentStatus( - media_perception::COMPONENT_STATUS_FAILED_TO_INSTALL)); + std::move(callback).Run(GetFailedToInstallComponentState()); return; } @@ -118,8 +126,7 @@ ExtensionsAPIClient::Get()->GetMediaPerceptionAPIDelegate(); if (!delegate) { LOG(WARNING) << "Could not get MediaPerceptionAPIDelegate."; - std::move(callback).Run(GetComponentStateForComponentStatus( - media_perception::COMPONENT_STATUS_FAILED_TO_INSTALL)); + std::move(callback).Run(GetFailedToInstallComponentState()); return; } @@ -132,17 +139,17 @@ void MediaPerceptionAPIManager::LoadComponentCallback( APISetAnalyticsComponentCallback callback, const std::string& mount_point) { - media_perception::ComponentState component_state; if (mount_point.empty()) { - component_state.status = - media_perception::COMPONENT_STATUS_FAILED_TO_INSTALL; - std::move(callback).Run(std::move(component_state)); + std::move(callback).Run(GetFailedToInstallComponentState()); return; } // If the new component is loaded, override the mount point. mount_point_ = mount_point; + + media_perception::ComponentState component_state; component_state.status = media_perception::COMPONENT_STATUS_INSTALLED; + component_state.version = ExtractVersionFromMountPoint(mount_point_); std::move(callback).Run(std::move(component_state)); return; }
diff --git a/extensions/browser/api/media_perception_private/media_perception_private_apitest.cc b/extensions/browser/api/media_perception_private/media_perception_private_apitest.cc index 65e8f57..345f4d3 100644 --- a/extensions/browser/api/media_perception_private/media_perception_private_apitest.cc +++ b/extensions/browser/api/media_perception_private/media_perception_private_apitest.cc
@@ -36,7 +36,7 @@ if (type == media_perception::COMPONENT_TYPE_LIGHT) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(load_callback), - "/run/imageloader/rtanalytics-light")); + "/run/imageloader/rtanalytics-light/1.0")); return; }
diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc index 53bfc0a..6c485b0c 100644 --- a/extensions/browser/api/web_request/web_request_api.cc +++ b/extensions/browser/api/web_request/web_request_api.cc
@@ -2095,7 +2095,7 @@ // In Public Session we only want to allow "cancel" (except for whitelisted // extensions which have no such restrictions). if (IsPublicSession() && - !extensions::IsWhitelistedForPublicSession(extension()->id()) && + !extensions::IsWhitelistedForPublicSession(extension_id_safe()) && (value->HasKey("redirectUrl") || value->HasKey(keys::kAuthCredentialsKey) || value->HasKey("requestHeaders") ||
diff --git a/extensions/browser/computed_hashes.cc b/extensions/browser/computed_hashes.cc index d66cc0c3..0a196a80 100644 --- a/extensions/browser/computed_hashes.cc +++ b/extensions/browser/computed_hashes.cc
@@ -101,9 +101,9 @@ bool ComputedHashes::Reader::GetHashes(const base::FilePath& relative_path, int* block_size, - std::vector<std::string>* hashes) { + std::vector<std::string>* hashes) const { base::FilePath path = relative_path.NormalizePathSeparatorsTo('/'); - std::map<base::FilePath, HashInfo>::iterator i = data_.find(path); + std::map<base::FilePath, HashInfo>::const_iterator i = data_.find(path); if (i == data_.end()) { // If we didn't find the entry using exact match, it's possible the // developer is using a path with some letters in the incorrect case, which @@ -121,7 +121,7 @@ if (i == data_.end()) return false; } - HashInfo& info = i->second; + const HashInfo& info = i->second; *block_size = info.first; *hashes = info.second; return true;
diff --git a/extensions/browser/computed_hashes.h b/extensions/browser/computed_hashes.h index 0451640..64b8320 100644 --- a/extensions/browser/computed_hashes.h +++ b/extensions/browser/computed_hashes.h
@@ -34,7 +34,7 @@ // out parameters. bool GetHashes(const base::FilePath& relative_path, int* block_size, - std::vector<std::string>* hashes); + std::vector<std::string>* hashes) const; private: typedef std::pair<int, std::vector<std::string> > HashInfo;
diff --git a/extensions/browser/content_hash_reader.cc b/extensions/browser/content_hash_reader.cc index 0355a63..b5e72a8 100644 --- a/extensions/browser/content_hash_reader.cc +++ b/extensions/browser/content_hash_reader.cc
@@ -33,12 +33,7 @@ extension_version_(extension_version.GetString()), extension_root_(extension_root), relative_path_(relative_path), - key_(key), - status_(NOT_INITIALIZED), - have_verified_contents_(false), - have_computed_hashes_(false), - file_missing_from_verified_contents_(false), - block_size_(0) {} + key_(key) {} ContentHashReader::~ContentHashReader() { } @@ -60,8 +55,6 @@ return false; } - have_verified_contents_ = true; - base::FilePath computed_hashes_path = file_util::GetComputedHashesPath(extension_root_); if (!base::PathExists(computed_hashes_path)) @@ -71,7 +64,7 @@ if (!reader.InitFromFile(computed_hashes_path)) return false; - have_computed_hashes_ = true; + has_content_hashes_ = true; // Extensions sometimes request resources that do not have an entry in // verified_contents.json. This can happen when an extension sends an XHR to a
diff --git a/extensions/browser/content_hash_reader.h b/extensions/browser/content_hash_reader.h index 0b30502..034a2b5 100644 --- a/extensions/browser/content_hash_reader.h +++ b/extensions/browser/content_hash_reader.h
@@ -39,14 +39,12 @@ // should likely be discarded. bool Init(); - // These return whether we found valid verified_contents.json / - // computed_hashes.json files respectively. Note that both of these can be - // true but we still didn't find an entry for |relative_path_| in them. - bool have_verified_contents() const { return have_verified_contents_; } - bool have_computed_hashes() const { return have_computed_hashes_; } + // Returns true if we found valid verified_contents.json and + // computed_hashes.json files. Note that this can be true even if we didn't + // find an entry for |relative_path_| in them. + bool has_content_hashes() const { return has_content_hashes_; } // Returns whether or not this resource's entry exists in - // verified_contents.json (given that both |have_verified_contents_| and - // |have_computed_hashes_| are true). + // verified_contents.json (given that |has_content_hashes_| is true. bool file_missing_from_verified_contents() const { return file_missing_from_verified_contents_; } @@ -72,14 +70,13 @@ base::FilePath relative_path_; ContentVerifierKey key_; - InitStatus status_; + InitStatus status_ = NOT_INITIALIZED; - bool have_verified_contents_; - bool have_computed_hashes_; - bool file_missing_from_verified_contents_; + bool has_content_hashes_ = false; + bool file_missing_from_verified_contents_ = false; // The blocksize used for generating the hashes. - int block_size_; + int block_size_ = 0; std::vector<std::string> hashes_;
diff --git a/extensions/browser/content_verify_job.cc b/extensions/browser/content_verify_job.cc index 60e1faa..c34f7ac 100644 --- a/extensions/browser/content_verify_job.cc +++ b/extensions/browser/content_verify_job.cc
@@ -175,8 +175,7 @@ // TODO(lazyboy): Make ContentHashReader::Init return an enum instead of // bool. This should make the following checks on |hash_reader_| easier // to digest and will avoid future bugs from creeping up. - if (!hash_reader_->have_verified_contents() || - !hash_reader_->have_computed_hashes()) { + if (!hash_reader_->has_content_hashes()) { DispatchFailureCallback(MISSING_ALL_HASHES); return; }
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index a3e8e32..9d3aa023 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h
@@ -1267,6 +1267,8 @@ METRICSPRIVATE_RECORDBOOLEAN, METRICSPRIVATE_RECORDENUMERATIONVALUE, DEVELOPERPRIVATE_NOTIFYDRAGINSTALLINPROGRESS, + AUTOTESTPRIVATE_GETPRINTERLIST, + DEVELOPERPRIVATE_GETEXTENSIONSIZE, // Last entry: Add new entries above, then run: // python tools/metrics/histograms/update_extension_histograms.py ENUM_BOUNDARY
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc index fc86fc0..cafc90e 100644 --- a/extensions/browser/extension_prefs.cc +++ b/extensions/browser/extension_prefs.cc
@@ -1691,6 +1691,10 @@ g_run_alerts_in_first_run_for_testing = true; } +void ExtensionPrefs::ClearExternalUninstallForTesting(const ExtensionId& id) { + DeleteExtensionPrefs(id); +} + ExtensionPrefs::ExtensionPrefs( content::BrowserContext* browser_context, PrefService* prefs,
diff --git a/extensions/browser/extension_prefs.h b/extensions/browser/extension_prefs.h index 8dfa757..6e34098f9 100644 --- a/extensions/browser/extension_prefs.h +++ b/extensions/browser/extension_prefs.h
@@ -562,6 +562,8 @@ // normally suppressed in first run will still trigger. static void SetRunAlertsInFirstRunForTest(); + void ClearExternalUninstallForTesting(const ExtensionId& id); + private: friend class ExtensionPrefsBlacklistedExtensions; // Unit test. friend class ExtensionPrefsComponentExtension; // Unit test.
diff --git a/extensions/common/api/media_perception_private.idl b/extensions/common/api/media_perception_private.idl index 599485b3..2f79834 100644 --- a/extensions/common/api/media_perception_private.idl +++ b/extensions/common/api/media_perception_private.idl
@@ -82,6 +82,9 @@ // The state of the media analytics downloadable component. dictionary ComponentState { ComponentStatus status; + + // The version string for the current component. + DOMString? version; }; // The parameters for processing a particular video stream.
diff --git a/extensions/test/data/media_perception_private/component/runtest.js b/extensions/test/data/media_perception_private/component/runtest.js index 41faa99..efba7019 100644 --- a/extensions/test/data/media_perception_private/component/runtest.js +++ b/extensions/test/data/media_perception_private/component/runtest.js
@@ -7,6 +7,7 @@ type: 'LIGHT', }, chrome.test.callbackPass(function(component_state) { chrome.test.assertEq('INSTALLED', component_state.status); + chrome.test.assertEq('1.0', component_state.version); })); }
diff --git a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_ordering_barrier.txt b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_ordering_barrier.txt new file mode 100644 index 0000000..bc2849a5 --- /dev/null +++ b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_ordering_barrier.txt
@@ -0,0 +1,78 @@ +Name + + CHROMIUM_ordering_barrier + +Name Strings + + GL_CHROMIUM_ordering_barrier + +Version + + Last Modifed Date: December 13, 2017 + +Dependencies + + OpenGL ES 2.0 is required. + +Overview + + This extension allows a client to order operations between contexts that + within the same scheduling group (stream). + + This extension introduces the concept of an "ordering barrier", "shallow + flush", and "shallow finish". Ordering barrier generalizes the implicit + flush ordering between contexts in a scheduling group (stream). Shallow + flush is used to submit commands to the server without a server-side flush. + Shallow finish is used to ensure that commands have executed on the server + without a server-side finish. + + Issuing an ordering barrier on a context implies that commands on other + contexts in the same scheduling group, which haven't been synchronized, + either by flush, ordering barrier, or sync tokens, must run after commands + on the current context. + +Issues + + None + +New Procedures and Functions + + The command + + void OrderingBarrierCHROMIUM() + + inserts an ordering barrier in the current command stream which forces any + unsynchronized commands in other contexts in the same scheduling group to + run after commands of the current context. Commands are not submitted to the + server unless a shallow flush or flush happens, or as a result of other + synchronization primitives such as sync tokens (see CHROMIUM_sync_point). + + The command + + void ShallowFlushCHROMIUM() + + + inserts an ordering barrier and submits commands in the current context to + the server. + + The command + + void ShallowFinishCHROMIUM() + + inserts an ordering barrier, submits commands, and returns after the + commands in the current context have executed. + +New Tokens + + None + +Errors + +New State + + None. + +Revision History + + 12/13/2017 Documented OrderingBarrierCHROMIUM, ShallowFlushCHROMIUM, and + ShallowFinishCHROMIUM.
diff --git a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_sync_point.txt b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_sync_point.txt index 1ee0b5e1..0e2d2cda 100644 --- a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_sync_point.txt +++ b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_sync_point.txt
@@ -18,20 +18,16 @@ This extension allows a client to order operations between contexts. - This extension introduces the concepts of "fence sync" and "sync token". - An inserted fence sync represents a position in the command stream of a - context. Sync tokens are generated from fence syncs and allow another - context to issue a "wait" command on the sync token. This wait command - will then guarantee that commands before the inserted fence sync are - submitted before commands after the sync token wait. + This extension introduces the concept of a "sync token" that can be passed + to other clients to issue a "wait" command for synchronization. Generating a + sync token inserts a fence into the command stream. This wait command will + then guarantee that commands before the inserted fence are submitted before + commands after the sync token wait. - This extension implements a small subset of ARB_sync, with weaker - guarantees. In particular it doesn't ensure commands are actually executed - by the server, it only guarantees submission order. - - It does however guarantee operation order with respect to - CreateAndConsumeTextureCHROMIUM and ProduceTextureDirectCHROMIUM from - CHROMIUM_texture_mailbox, if present. + Combined with mailboxes from CHROMIUM_texture_mailbox, which are exported + using CreateAndConsumeTextureCHROMIUM and imported using + ProduceTextureDirectCHROMIUM commands, this allows clients across processes + to synchronize resources. Issues @@ -41,61 +37,39 @@ The command - uint64 InsertFenceSyncCHROMIUM() + void GenSyncTokenCHROMIUM(GLbyte *sync_token) - inserts a fence sync in the current command stream. The fence sync is - signaled when previous commands have been submitted to the server, or when - the context is destroyed, whichever happens first. The fence sync name is - only visible for the current context. The returned fence sync name cannot - be waited upon directly, but once the command is flushed to the server, - it can be converted to a sync token using GenSyncTokenCHROMIUM, which is - waitable. - - The command - - void GenSyncTokenCHROMIUM(uint64 fence_sync, GLbyte *sync_token) - - converts <fence_sync> which is only visible to the current context to a - sync token which may be waited upon by any contexts on the same server. - The <fence_sync> command must be flushed before this function may be - called, otherwise an INVALID_OPERATION error is generated. The use of - ShallowFlushCHROMIUM is enough for the command to be flushed to the - server. The generated <sync_token> must be generated on the same context - as when InsertFenceSyncCHROMIUM was called. The <sync_token> can be passed - and used by any context on the same server, including other context groups. + inserts a fence into the current context's command stream and returns a + <sync_token>. The <sync_token> can be passed and used by any context on the + same server, including other context groups. The fence also implies an + ordering barrier between contexts in the current scheduling group (stream). + An INVALID_OPERATION error is generated if <sync_token> is NULL. <sync_token> returns a GL_SYNC_TOKEN_SIZE_CHROMIUM byte sized name. The command - void GenUnverifiedSyncTokenCHROMIUM(uint64 fence_sync, - GLbyte *sync_token) + void GenUnverifiedSyncTokenCHROMIUM(GLbyte *sync_token) - converts <fence_sync>, which is only visible to the current context, to a - sync token, which may be waited upon by a context which only needs flush - order guarantee with respect to the fence sync context. For example, if - the two contexts are on the same channel but on different streams, flush - order guarantee is enough to guarantee that the server will receive the - release command before the wait command. The <fence_sync> command must be - flushed or separated by an ordering barrier before this function may be - called, otherwise an INVALID_OPERATION error is generated. For chromium - specific flushes and ordering barriers, see ShallowFlushCHROMIUM and - OrderingBarrierCHROMIUM. The generated <sync_token> must be generated on - the same context as when InsertFenceSyncCHROMIUM was called. + inserts a fence into the current context's command stream and returns a + <sync_token>. The <sync_token> can be passed and used by any context on the + same client (process), including other context groups. The fence also + implies an ordering barrier between contexts in the current scheduling group + (stream). However, to pass the <sync_token> to a context in another client + (process), the <sync_token> must be verified using VerifySyncTokensCHROMIUM. + An INVALID_OPERATION error is generated if <sync_token> is NULL. The command void VerifySyncTokensCHROMIUM(GLbyte **sync_tokens, GLsizei count) - verifies array <sync_tokens> of length <count> and ensures that these - sync tokens have all been verified. The generated sync token did not have - to be generated from the same context but it must be from a context which - flush order guarantee is enough to guarantee order. For example, contexts - which live on the same channel may verify sync tokens for one another. - If a sync token was generated by GenUnverifiedSyncTokenCHROMIUM and the - corresponding context is unable to verify it, an INVALID_OPERATION error - is generated. Sync tokens which have already been verified are ignored, if - all sync tokens were already verified then nothing will be done. + verifies array <sync_tokens> of length <count> and ensures that these sync + tokens have all been verified. The generated sync token did not have to be + generated from the same context but it must belong to the same client + (process). If a sync token was generated by GenUnverifiedSyncTokenCHROMIUM + and but isn't from the same client (process), an INVALID_OPERATION error is + generated. Sync tokens which have already been verified are ignored, if all + sync tokens were already verified then nothing will be done. The command @@ -103,12 +77,11 @@ causes the current context to stop submitting commands until the specified fence sync becomes signaled. This is implemented as a server-side wait. - <sync_token> is a sync token generated by GenSyncTokenCHROMIUM. If - <sync_token> was generated by GenUnverifiedSyncTokenCHROMIUM and the - corresponding fence sync context required more than just flush ordering - to guarantee synchronization, an INVALID_OPERATION error is generated. If - <sync_token> isn't a valid sync token returned by GenSyncTokenCHROMIUM or - GenUnverifiedSyncTokenCHROMIUM, the result is undefined. + <sync_token> must be a sync token generated by GenSyncTokenCHROMIUM, or + generated by GenUnverifiedSyncTokenCHROMIUM and from the same client + (process). If <sync_token> isn't a valid sync token returned by + GenSyncTokenCHROMIUM or GenUnverifiedSyncTokenCHROMIUM, the result is + undefined. New Tokens @@ -121,21 +94,9 @@ INVALID_VALUE is generated if the <sync_token> parameter of GenSyncTokenCHROMIUM or GenUnverifiedSyncTokenCHROMIUM is NULL. - INVALID_VALUE is generated if the <fence_sync> parameter of - GenSyncTokenCHROMIUM or GenUnverifiedSyncTokenCHROMIUM is not a - valid local fence sync name. - - INVALID_OPERATION is generated if the <fence_sync> parameter of - GenSyncTokenCHROMIUM or has not been flushed to the server. - - INVALID_OPERATION is generated if the <fence_sync> parameter of - GenUnverifiedSyncTokenCHROMIUM or has not been flushed to the server - or queued to be flushed using an ordering barrier. - INVALID_OPERATION is generated if the <sync_token> parameter of WaitSyncTokenCHROMIUM or VerifySyncTokensCHROMIUM was generated using - GenUnverifiedSyncTokenCHROMIUM, but the two contexts must be synchronized - with more than just flush order. + GenUnverifiedSyncTokenCHROMIUM but is not from the same client (process). New State @@ -154,3 +115,7 @@ ordering barrier and added proper error values. 11/25/2015 Added function VerifySyncTokensCHROMIUM. + + 12/13/2017 Simplified functions GenSyncTokenCHROMIUM and + GenUnverifiedSyncTokenCHROMIUM to generate the fence + implicitly. Removed function InsertFenceSyncCHROMIUM.
diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h index 299c6d3..449e22c 100644 --- a/gpu/GLES2/gl2chromium_autogen.h +++ b/gpu/GLES2/gl2chromium_autogen.h
@@ -315,7 +315,6 @@ #define glTraceEndCHROMIUM GLES2_GET_FUN(TraceEndCHROMIUM) #define glDiscardFramebufferEXT GLES2_GET_FUN(DiscardFramebufferEXT) #define glLoseContextCHROMIUM GLES2_GET_FUN(LoseContextCHROMIUM) -#define glInsertFenceSyncCHROMIUM GLES2_GET_FUN(InsertFenceSyncCHROMIUM) #define glGenSyncTokenCHROMIUM GLES2_GET_FUN(GenSyncTokenCHROMIUM) #define glGenUnverifiedSyncTokenCHROMIUM \ GLES2_GET_FUN(GenUnverifiedSyncTokenCHROMIUM)
diff --git a/gpu/GLES2/gl2extchromium.h b/gpu/GLES2/gl2extchromium.h index 1ec6c20..25a07e4 100644 --- a/gpu/GLES2/gl2extchromium.h +++ b/gpu/GLES2/gl2extchromium.h
@@ -661,22 +661,16 @@ #endif #ifdef GL_GLEXT_PROTOTYPES -GL_APICALL GLuint GL_APIENTRY glInsertSyncPointCHROMIUM(); -GL_APICALL GLuint64 GL_APIENTRY glInsertFenceSyncCHROMIUM(); -GL_APICALL void GL_APIENTRY glGenSyncTokenCHROMIUM(GLuint64 fence_sync, - GLbyte* sync_token); -GL_APICALL void GL_APIENTRY glGenUnverifiedSyncTokenCHROMIUM( - GLuint64 fence_sync, GLbyte* sync_token); +GL_APICALL void GL_APIENTRY glGenSyncTokenCHROMIUM(GLbyte* sync_token); +GL_APICALL void GL_APIENTRY +glGenUnverifiedSyncTokenCHROMIUM(GLbyte* sync_token); GL_APICALL void GL_APIENTRY glVerifySyncTokensCHROMIUM(GLbyte **sync_tokens, GLsizei count); GL_APICALL void GL_APIENTRY glWaitSyncTokenCHROMIUM(const GLbyte* sync_token); #endif -typedef GLuint (GL_APIENTRYP PFNGLINSERTSYNCPOINTCHROMIUMPROC) (); -typedef GLuint64 (GL_APIENTRYP PFNGLINSERTFENCESYNCCHROMIUMPROC) (); -typedef void (GL_APIENTRYP PFNGLGENSYNCTOKENCHROMIUMPROC) (GLuint64 fence_sync, - GLbyte* sync_token); -typedef void (GL_APIENTRYP PFNGLGENUNVERIFIEDSYNCTOKENCHROMIUMPROC) ( - GLuint64 fence_sync, GLbyte* sync_token); +typedef void(GL_APIENTRYP PFNGLGENSYNCTOKENCHROMIUMPROC)(GLbyte* sync_token); +typedef void(GL_APIENTRYP PFNGLGENUNVERIFIEDSYNCTOKENCHROMIUMPROC)( + GLbyte* sync_token); typedef void (GL_APIENTRYP PFNGLVERIFYSYNCTOKENSCHROMIUMPROC) ( GLbyte **sync_tokens, GLsizei count); typedef void (GL_APIENTRYP PFNGLWAITSYNCTOKENCHROMIUM) (
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 1c2ec9f4..31e44550 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -4311,15 +4311,15 @@ }, 'ShallowFinishCHROMIUM': { 'type': 'NoCommand', - 'extension': True, + 'extension': 'CHROMIUM_ordering_barrier', }, 'ShallowFlushCHROMIUM': { 'type': 'NoCommand', - 'extension': "CHROMIUM_miscellaneous", + 'extension': 'CHROMIUM_ordering_barrier', }, 'OrderingBarrierCHROMIUM': { 'type': 'NoCommand', - 'extension': "CHROMIUM_miscellaneous", + 'extension': 'CHROMIUM_ordering_barrier', }, 'TraceBeginCHROMIUM': { 'type': 'Custom', @@ -4352,6 +4352,7 @@ }, 'InsertFenceSyncCHROMIUM': { 'type': 'Custom', + 'internal': True, 'impl_func': False, 'cmd_args': 'GLuint64 release_count', 'extension': "CHROMIUM_sync_point",
diff --git a/gpu/command_buffer/client/client_test_helper.h b/gpu/command_buffer/client/client_test_helper.h index c23395d0..d7b46885 100644 --- a/gpu/command_buffer/client/client_test_helper.h +++ b/gpu/command_buffer/client/client_test_helper.h
@@ -118,9 +118,6 @@ MOCK_CONST_METHOD0(GetCommandBufferID, CommandBufferId()); MOCK_METHOD0(FlushPendingWork, void()); MOCK_METHOD0(GenerateFenceSyncRelease, uint64_t()); - MOCK_METHOD1(IsFenceSyncRelease, bool(uint64_t release)); - MOCK_METHOD1(IsFenceSyncFlushed, bool(uint64_t release)); - MOCK_METHOD1(IsFenceSyncFlushReceived, bool(uint64_t release)); MOCK_METHOD1(IsFenceSyncReleased, bool(uint64_t release)); MOCK_METHOD2(SignalSyncToken, void(const SyncToken& sync_token, const base::Closure& callback));
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index d007cf77..0470e27 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -1431,16 +1431,11 @@ void GL_APIENTRY GLES2LoseContextCHROMIUM(GLenum current, GLenum other) { gles2::GetGLContext()->LoseContextCHROMIUM(current, other); } -GLuint64 GL_APIENTRY GLES2InsertFenceSyncCHROMIUM() { - return gles2::GetGLContext()->InsertFenceSyncCHROMIUM(); +void GL_APIENTRY GLES2GenSyncTokenCHROMIUM(GLbyte* sync_token) { + gles2::GetGLContext()->GenSyncTokenCHROMIUM(sync_token); } -void GL_APIENTRY GLES2GenSyncTokenCHROMIUM(GLuint64 fence_sync, - GLbyte* sync_token) { - gles2::GetGLContext()->GenSyncTokenCHROMIUM(fence_sync, sync_token); -} -void GL_APIENTRY GLES2GenUnverifiedSyncTokenCHROMIUM(GLuint64 fence_sync, - GLbyte* sync_token) { - gles2::GetGLContext()->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token); +void GL_APIENTRY GLES2GenUnverifiedSyncTokenCHROMIUM(GLbyte* sync_token) { + gles2::GetGLContext()->GenUnverifiedSyncTokenCHROMIUM(sync_token); } void GL_APIENTRY GLES2VerifySyncTokensCHROMIUM(GLbyte** sync_tokens, GLsizei count) { @@ -2904,10 +2899,6 @@ reinterpret_cast<GLES2FunctionPointer>(glLoseContextCHROMIUM), }, { - "glInsertFenceSyncCHROMIUM", - reinterpret_cast<GLES2FunctionPointer>(glInsertFenceSyncCHROMIUM), - }, - { "glGenSyncTokenCHROMIUM", reinterpret_cast<GLES2FunctionPointer>(glGenSyncTokenCHROMIUM), },
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index 618c0d1..e2dbfb3 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -3855,9 +3855,11 @@ // Adds extensions implemented on client side only. if (name == GL_EXTENSIONS) { str += std::string(str.empty() ? "" : " ") + - "GL_EXT_unpack_subimage " + "GL_CHROMIUM_image " "GL_CHROMIUM_map_sub " - "GL_CHROMIUM_image"; + "GL_CHROMIUM_ordering_barrier " + "GL_CHROMIUM_sync_point " + "GL_EXT_unpack_subimage"; } // Because of WebGL the extensions can change. We have to cache each unique @@ -6210,27 +6212,17 @@ lost_context_callback_ = callback; } -GLuint64 GLES2Implementation::InsertFenceSyncCHROMIUM() { - const uint64_t release = gpu_control_->GenerateFenceSyncRelease(); - helper_->InsertFenceSyncCHROMIUM(release); - return release; -} - -void GLES2Implementation::GenSyncTokenCHROMIUM(GLuint64 fence_sync, - GLbyte* sync_token) { +void GLES2Implementation::GenSyncTokenCHROMIUM(GLbyte* sync_token) { if (!sync_token) { SetGLError(GL_INVALID_VALUE, "glGenSyncTokenCHROMIUM", "empty sync_token"); return; - } else if (!gpu_control_->IsFenceSyncRelease(fence_sync)) { - SetGLError(GL_INVALID_VALUE, "glGenSyncTokenCHROMIUM", - "invalid fence sync"); - return; - } else if (!gpu_control_->IsFenceSyncFlushReceived(fence_sync)) { - SetGLError(GL_INVALID_OPERATION, "glGenSyncTokenCHROMIUM", - "fence sync must be flushed before generating sync token"); - return; } + uint64_t fence_sync = gpu_control_->GenerateFenceSyncRelease(); + helper_->InsertFenceSyncCHROMIUM(fence_sync); + helper_->CommandBufferHelper::OrderingBarrier(); + gpu_control_->EnsureWorkVisible(); + // Copy the data over after setting the data to ensure alignment. SyncToken sync_token_data(gpu_control_->GetNamespaceID(), 0, gpu_control_->GetCommandBufferID(), fence_sync); @@ -6238,22 +6230,17 @@ memcpy(sync_token, &sync_token_data, sizeof(sync_token_data)); } -void GLES2Implementation::GenUnverifiedSyncTokenCHROMIUM(GLuint64 fence_sync, - GLbyte* sync_token) { +void GLES2Implementation::GenUnverifiedSyncTokenCHROMIUM(GLbyte* sync_token) { if (!sync_token) { SetGLError(GL_INVALID_VALUE, "glGenUnverifiedSyncTokenCHROMIUM", "empty sync_token"); return; - } else if (!gpu_control_->IsFenceSyncRelease(fence_sync)) { - SetGLError(GL_INVALID_VALUE, "glGenUnverifiedSyncTokenCHROMIUM", - "invalid fence sync"); - return; - } else if (!gpu_control_->IsFenceSyncFlushed(fence_sync)) { - SetGLError(GL_INVALID_OPERATION, "glGenUnverifiedSyncTokenCHROMIUM", - "fence sync must be flushed before generating sync token"); - return; } + uint64_t fence_sync = gpu_control_->GenerateFenceSyncRelease(); + helper_->InsertFenceSyncCHROMIUM(fence_sync); + helper_->CommandBufferHelper::OrderingBarrier(); + // Copy the data over after setting the data to ensure alignment. SyncToken sync_token_data(gpu_control_->GetNamespaceID(), 0, gpu_control_->GetCommandBufferID(), fence_sync);
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index 3ed75eb..7e9fc1a9 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -1008,12 +1008,9 @@ void LoseContextCHROMIUM(GLenum current, GLenum other) override; -GLuint64 InsertFenceSyncCHROMIUM() override; +void GenSyncTokenCHROMIUM(GLbyte* sync_token) override; -void GenSyncTokenCHROMIUM(GLuint64 fence_sync, GLbyte* sync_token) override; - -void GenUnverifiedSyncTokenCHROMIUM(GLuint64 fence_sync, - GLbyte* sync_token) override; +void GenUnverifiedSyncTokenCHROMIUM(GLbyte* sync_token) override; void VerifySyncTokensCHROMIUM(GLbyte** sync_tokens, GLsizei count) override;
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc index 2fd5ae0..664ed66f0 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -3196,9 +3196,11 @@ // GL_CHROMIUM_map_sub is hard coded into GLES2Implementation. const char* expected_str = "foobar " - "GL_EXT_unpack_subimage " + "GL_CHROMIUM_image " "GL_CHROMIUM_map_sub " - "GL_CHROMIUM_image"; + "GL_CHROMIUM_ordering_barrier " + "GL_CHROMIUM_sync_point " + "GL_EXT_unpack_subimage"; const char kBad = 0x12; struct Cmds { cmd::SetBucketSize set_bucket_size1; @@ -3918,60 +3920,33 @@ EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); } -TEST_F(GLES2ImplementationTest, InsertFenceSyncCHROMIUM) { - const GLuint64 kFenceSync = 123u; - EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease()) - .WillOnce(Return(kFenceSync)); - - struct Cmds { - cmds::InsertFenceSyncCHROMIUM insert_fence_sync; - }; - Cmds expected; - expected.insert_fence_sync.Init(kFenceSync); - - const GLuint64 fence_sync = gl_->InsertFenceSyncCHROMIUM(); - EXPECT_EQ(kFenceSync, fence_sync); - EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); -} - TEST_F(GLES2ImplementationTest, GenSyncTokenCHROMIUM) { const CommandBufferNamespace kNamespaceId = CommandBufferNamespace::GPU_IO; const CommandBufferId kCommandBufferId = CommandBufferId::FromUnsafeValue(234u); const GLuint64 kFenceSync = 123u; - GLbyte sync_token_data[GL_SYNC_TOKEN_SIZE_CHROMIUM]; + SyncToken sync_token; EXPECT_CALL(*gpu_control_, GetNamespaceID()) .WillRepeatedly(Return(kNamespaceId)); EXPECT_CALL(*gpu_control_, GetCommandBufferID()) .WillRepeatedly(Return(kCommandBufferId)); - gl_->GenSyncTokenCHROMIUM(kFenceSync, nullptr); - EXPECT_EQ(GL_INVALID_VALUE, CheckError()); - - EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync)) - .WillOnce(Return(false)); - gl_->GenSyncTokenCHROMIUM(kFenceSync, sync_token_data); - EXPECT_EQ(GL_INVALID_VALUE, CheckError()); - - EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync)) - .WillOnce(Return(true)); - EXPECT_CALL(*gpu_control_, IsFenceSyncFlushReceived(kFenceSync)) - .WillOnce(Return(false)); - gl_->GenSyncTokenCHROMIUM(kFenceSync, sync_token_data); - EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); - - EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync)) - .WillOnce(Return(true)); - EXPECT_CALL(*gpu_control_, IsFenceSyncFlushReceived(kFenceSync)) - .WillOnce(Return(true)); - ClearCommands(); - gl_->GenSyncTokenCHROMIUM(kFenceSync, sync_token_data); + gl_->GenSyncTokenCHROMIUM(nullptr); EXPECT_TRUE(NoCommandsWritten()); + EXPECT_EQ(GL_INVALID_VALUE, CheckError()); + + const void* commands = GetPut(); + cmds::InsertFenceSyncCHROMIUM insert_fence_sync; + insert_fence_sync.Init(kFenceSync); + + EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease()) + .WillOnce(Return(kFenceSync)); + EXPECT_CALL(*gpu_control_, EnsureWorkVisible()); + gl_->GenSyncTokenCHROMIUM(sync_token.GetData()); + EXPECT_EQ(0, memcmp(&insert_fence_sync, commands, sizeof(insert_fence_sync))); EXPECT_EQ(GL_NO_ERROR, CheckError()); - SyncToken sync_token; - memcpy(&sync_token, sync_token_data, sizeof(SyncToken)); EXPECT_TRUE(sync_token.verified_flush()); EXPECT_EQ(kNamespaceId, sync_token.namespace_id()); EXPECT_EQ(kCommandBufferId, sync_token.command_buffer_id()); @@ -3983,39 +3958,27 @@ const CommandBufferId kCommandBufferId = CommandBufferId::FromUnsafeValue(234u); const GLuint64 kFenceSync = 123u; - GLbyte sync_token_data[GL_SYNC_TOKEN_SIZE_CHROMIUM]; + SyncToken sync_token; EXPECT_CALL(*gpu_control_, GetNamespaceID()) .WillRepeatedly(Return(kNamespaceId)); EXPECT_CALL(*gpu_control_, GetCommandBufferID()) .WillRepeatedly(Return(kCommandBufferId)); - gl_->GenUnverifiedSyncTokenCHROMIUM(kFenceSync, nullptr); - EXPECT_EQ(GL_INVALID_VALUE, CheckError()); - - EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync)) - .WillOnce(Return(false)); - gl_->GenUnverifiedSyncTokenCHROMIUM(kFenceSync, sync_token_data); - EXPECT_EQ(GL_INVALID_VALUE, CheckError()); - - EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync)) - .WillOnce(Return(true)); - EXPECT_CALL(*gpu_control_, IsFenceSyncFlushed(kFenceSync)) - .WillOnce(Return(false)); - gl_->GenUnverifiedSyncTokenCHROMIUM(kFenceSync, sync_token_data); - EXPECT_EQ(GL_INVALID_OPERATION, CheckError()); - - EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync)) - .WillOnce(Return(true)); - EXPECT_CALL(*gpu_control_, IsFenceSyncFlushed(kFenceSync)) - .WillOnce(Return(true)); - ClearCommands(); - gl_->GenUnverifiedSyncTokenCHROMIUM(kFenceSync, sync_token_data); + gl_->GenUnverifiedSyncTokenCHROMIUM(nullptr); EXPECT_TRUE(NoCommandsWritten()); + EXPECT_EQ(GL_INVALID_VALUE, CheckError()); + + const void* commands = GetPut(); + cmds::InsertFenceSyncCHROMIUM insert_fence_sync; + insert_fence_sync.Init(kFenceSync); + + EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease()) + .WillOnce(Return(kFenceSync)); + gl_->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); + EXPECT_EQ(0, memcmp(&insert_fence_sync, commands, sizeof(insert_fence_sync))); EXPECT_EQ(GL_NO_ERROR, CheckError()); - SyncToken sync_token; - memcpy(&sync_token, sync_token_data, sizeof(SyncToken)); EXPECT_FALSE(sync_token.verified_flush()); EXPECT_EQ(kNamespaceId, sync_token.namespace_id()); EXPECT_EQ(kCommandBufferId, sync_token.command_buffer_id()); @@ -4034,20 +3997,18 @@ CommandBufferId::FromUnsafeValue(234u); const GLuint64 kFenceSync = 123u; gpu::SyncToken sync_token; - GLbyte* sync_token_datas[] = { sync_token.GetData() }; + GLbyte* sync_token_datas[] = {sync_token.GetData()}; EXPECT_CALL(*gpu_control_, GetNamespaceID()) .WillRepeatedly(Return(kNamespaceId)); EXPECT_CALL(*gpu_control_, GetCommandBufferID()) .WillRepeatedly(Return(kCommandBufferId)); - EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync)) - .WillOnce(Return(true)); - EXPECT_CALL(*gpu_control_, IsFenceSyncFlushed(kFenceSync)) - .WillOnce(Return(true)); - gl_->GenUnverifiedSyncTokenCHROMIUM(kFenceSync, sync_token.GetData()); - ASSERT_TRUE(sync_token.HasData()); - ASSERT_FALSE(sync_token.verified_flush()); + EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease()) + .WillOnce(Return(kFenceSync)); + gl_->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); + EXPECT_TRUE(sync_token.HasData()); + EXPECT_FALSE(sync_token.verified_flush()); ClearCommands(); EXPECT_CALL(*gpu_control_, CanWaitUnverifiedSyncToken(sync_token)) @@ -4088,7 +4049,7 @@ const GLuint64 kFenceSync2 = 234u; gpu::SyncToken sync_token1; gpu::SyncToken sync_token2; - GLbyte* sync_token_datas[] = { sync_token1.GetData(), sync_token2.GetData() }; + GLbyte* sync_token_datas[] = {sync_token1.GetData(), sync_token2.GetData()}; EXPECT_CALL(*gpu_control_, GetNamespaceID()) .WillRepeatedly(Return(kNamespaceId)); @@ -4096,22 +4057,18 @@ .WillRepeatedly(Return(kCommandBufferId)); // Generate sync token 1. - EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync1)) - .WillOnce(Return(true)); - EXPECT_CALL(*gpu_control_, IsFenceSyncFlushed(kFenceSync1)) - .WillOnce(Return(true)); - gl_->GenUnverifiedSyncTokenCHROMIUM(kFenceSync1, sync_token1.GetData()); - ASSERT_TRUE(sync_token1.HasData()); - ASSERT_FALSE(sync_token1.verified_flush()); + EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease()) + .WillOnce(Return(kFenceSync1)); + gl_->GenUnverifiedSyncTokenCHROMIUM(sync_token1.GetData()); + EXPECT_TRUE(sync_token1.HasData()); + EXPECT_FALSE(sync_token1.verified_flush()); // Generate sync token 2. - EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync2)) - .WillOnce(Return(true)); - EXPECT_CALL(*gpu_control_, IsFenceSyncFlushed(kFenceSync2)) - .WillOnce(Return(true)); - gl_->GenUnverifiedSyncTokenCHROMIUM(kFenceSync2, sync_token2.GetData()); - ASSERT_TRUE(sync_token2.HasData()); - ASSERT_FALSE(sync_token2.verified_flush()); + EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease()) + .WillOnce(Return(kFenceSync2)); + gl_->GenUnverifiedSyncTokenCHROMIUM(sync_token2.GetData()); + EXPECT_TRUE(sync_token2.HasData()); + EXPECT_FALSE(sync_token2.verified_flush()); // Ensure proper sequence of checking and validating. Sequence sequence; @@ -4121,10 +4078,8 @@ EXPECT_CALL(*gpu_control_, CanWaitUnverifiedSyncToken(sync_token2)) .InSequence(sequence) .WillOnce(Return(true)); - EXPECT_CALL(*gpu_control_, EnsureWorkVisible()) - .InSequence(sequence); + EXPECT_CALL(*gpu_control_, EnsureWorkVisible()).InSequence(sequence); gl_->VerifySyncTokensCHROMIUM(sync_token_datas, arraysize(sync_token_datas)); - EXPECT_TRUE(NoCommandsWritten()); EXPECT_EQ(GL_NO_ERROR, CheckError()); EXPECT_TRUE(sync_token1.verified_flush()); @@ -4156,29 +4111,31 @@ } TEST_F(GLES2ImplementationTest, WaitSyncTokenCHROMIUM) { - CommandBufferNamespace kNamespaceId = CommandBufferNamespace::GPU_IO; - CommandBufferId kCommandBufferId = CommandBufferId::FromUnsafeValue(234u); - GLuint64 kFenceSync = 456u; + const CommandBufferNamespace kNamespaceId = CommandBufferNamespace::GPU_IO; + const CommandBufferId kCommandBufferId = + CommandBufferId::FromUnsafeValue(234u); + const GLuint64 kFenceSync = 456u; gpu::SyncToken sync_token; GLbyte* sync_token_data = sync_token.GetData(); - EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(kFenceSync)) - .WillOnce(Return(true)); - EXPECT_CALL(*gpu_control_, IsFenceSyncFlushReceived(kFenceSync)) - .WillOnce(Return(true)); - EXPECT_CALL(*gpu_control_, GetNamespaceID()).WillOnce(Return(kNamespaceId)); - EXPECT_CALL(*gpu_control_, GetCommandBufferID()) - .WillOnce(Return(kCommandBufferId)); - gl_->GenSyncTokenCHROMIUM(kFenceSync, sync_token_data); - struct Cmds { + cmds::InsertFenceSyncCHROMIUM insert_fence_sync; cmds::WaitSyncTokenCHROMIUM wait_sync_token; }; Cmds expected; + expected.insert_fence_sync.Init(kFenceSync); expected.wait_sync_token.Init(kNamespaceId, kCommandBufferId.GetUnsafeValue(), kFenceSync); + EXPECT_CALL(*gpu_control_, GetNamespaceID()).WillOnce(Return(kNamespaceId)); + EXPECT_CALL(*gpu_control_, GetCommandBufferID()) + .WillOnce(Return(kCommandBufferId)); + EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease()) + .WillOnce(Return(kFenceSync)); + EXPECT_CALL(*gpu_control_, EnsureWorkVisible()); + gl_->GenSyncTokenCHROMIUM(sync_token_data); + EXPECT_CALL(*gpu_control_, WaitSyncTokenHint(sync_token)); gl_->WaitSyncTokenCHROMIUM(sync_token_data); EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); @@ -4498,19 +4455,20 @@ } TEST_F(GLES2ImplementationTest, SignalSyncToken) { - EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease()).WillOnce(Return(1)); - const uint64_t fence_sync = gl_->InsertFenceSyncCHROMIUM(); - gl_->ShallowFlushCHROMIUM(); + const CommandBufferNamespace kNamespaceId = CommandBufferNamespace::GPU_IO; + const CommandBufferId kCommandBufferId = CommandBufferId::FromUnsafeValue(1); + const uint64_t kFenceSync = 123u; - EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(fence_sync)) - .WillOnce(Return(true)); - EXPECT_CALL(*gpu_control_, IsFenceSyncFlushReceived(fence_sync)) - .WillOnce(Return(true)); - EXPECT_CALL(*gpu_control_, GetNamespaceID()).WillOnce(Return(GPU_IO)); + EXPECT_CALL(*gpu_control_, GetNamespaceID()) + .WillRepeatedly(Return(kNamespaceId)); EXPECT_CALL(*gpu_control_, GetCommandBufferID()) - .WillOnce(Return(CommandBufferId::FromUnsafeValue(1))); + .WillRepeatedly(Return(kCommandBufferId)); + + EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease()) + .WillOnce(Return(kFenceSync)); + EXPECT_CALL(*gpu_control_, EnsureWorkVisible()); gpu::SyncToken sync_token; - gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + gl_->GenSyncTokenCHROMIUM(sync_token.GetData()); int signaled_count = 0; @@ -4529,19 +4487,18 @@ } TEST_F(GLES2ImplementationTest, SignalSyncTokenAfterContextLoss) { - EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease()).WillOnce(Return(1)); - const uint64_t fence_sync = gl_->InsertFenceSyncCHROMIUM(); - gl_->ShallowFlushCHROMIUM(); + const CommandBufferNamespace kNamespaceId = CommandBufferNamespace::GPU_IO; + const CommandBufferId kCommandBufferId = CommandBufferId::FromUnsafeValue(1); + const uint64_t kFenceSync = 123u; - EXPECT_CALL(*gpu_control_, IsFenceSyncRelease(fence_sync)) - .WillOnce(Return(true)); - EXPECT_CALL(*gpu_control_, IsFenceSyncFlushReceived(fence_sync)) - .WillOnce(Return(true)); - EXPECT_CALL(*gpu_control_, GetNamespaceID()).WillOnce(Return(GPU_IO)); + EXPECT_CALL(*gpu_control_, GetNamespaceID()).WillOnce(Return(kNamespaceId)); EXPECT_CALL(*gpu_control_, GetCommandBufferID()) - .WillOnce(Return(CommandBufferId::FromUnsafeValue(1))); + .WillOnce(Return(kCommandBufferId)); + EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease()) + .WillOnce(Return(kFenceSync)); + EXPECT_CALL(*gpu_control_, EnsureWorkVisible()); gpu::SyncToken sync_token; - gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + gl_->GenSyncTokenCHROMIUM(sync_token.GetData()); int signaled_count = 0;
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h index d44ccd22..9d1626f2 100644 --- a/gpu/command_buffer/client/gles2_interface_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -740,10 +740,8 @@ GLsizei count, const GLenum* attachments) = 0; virtual void LoseContextCHROMIUM(GLenum current, GLenum other) = 0; -virtual GLuint64 InsertFenceSyncCHROMIUM() = 0; -virtual void GenSyncTokenCHROMIUM(GLuint64 fence_sync, GLbyte* sync_token) = 0; -virtual void GenUnverifiedSyncTokenCHROMIUM(GLuint64 fence_sync, - GLbyte* sync_token) = 0; +virtual void GenSyncTokenCHROMIUM(GLbyte* sync_token) = 0; +virtual void GenUnverifiedSyncTokenCHROMIUM(GLbyte* sync_token) = 0; virtual void VerifySyncTokensCHROMIUM(GLbyte** sync_tokens, GLsizei count) = 0; virtual void WaitSyncTokenCHROMIUM(const GLbyte* sync_token) = 0; virtual void DrawBuffersEXT(GLsizei count, const GLenum* bufs) = 0;
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h index 4e8e909d..241a82cb 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -718,10 +718,8 @@ GLsizei count, const GLenum* attachments) override; void LoseContextCHROMIUM(GLenum current, GLenum other) override; -GLuint64 InsertFenceSyncCHROMIUM() override; -void GenSyncTokenCHROMIUM(GLuint64 fence_sync, GLbyte* sync_token) override; -void GenUnverifiedSyncTokenCHROMIUM(GLuint64 fence_sync, - GLbyte* sync_token) override; +void GenSyncTokenCHROMIUM(GLbyte* sync_token) override; +void GenUnverifiedSyncTokenCHROMIUM(GLbyte* sync_token) override; void VerifySyncTokensCHROMIUM(GLbyte** sync_tokens, GLsizei count) override; void WaitSyncTokenCHROMIUM(const GLbyte* sync_token) override; void DrawBuffersEXT(GLsizei count, const GLenum* bufs) override;
diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h index d50f56e..92f0e049 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -975,13 +975,8 @@ const GLenum* /* attachments */) {} void GLES2InterfaceStub::LoseContextCHROMIUM(GLenum /* current */, GLenum /* other */) {} -GLuint64 GLES2InterfaceStub::InsertFenceSyncCHROMIUM() { - return 0; -} -void GLES2InterfaceStub::GenSyncTokenCHROMIUM(GLuint64 /* fence_sync */, - GLbyte* /* sync_token */) {} +void GLES2InterfaceStub::GenSyncTokenCHROMIUM(GLbyte* /* sync_token */) {} void GLES2InterfaceStub::GenUnverifiedSyncTokenCHROMIUM( - GLuint64 /* fence_sync */, GLbyte* /* sync_token */) {} void GLES2InterfaceStub::VerifySyncTokensCHROMIUM(GLbyte** /* sync_tokens */, GLsizei /* count */) {}
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h index e7edf775..e8e147b 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -718,10 +718,8 @@ GLsizei count, const GLenum* attachments) override; void LoseContextCHROMIUM(GLenum current, GLenum other) override; -GLuint64 InsertFenceSyncCHROMIUM() override; -void GenSyncTokenCHROMIUM(GLuint64 fence_sync, GLbyte* sync_token) override; -void GenUnverifiedSyncTokenCHROMIUM(GLuint64 fence_sync, - GLbyte* sync_token) override; +void GenSyncTokenCHROMIUM(GLbyte* sync_token) override; +void GenUnverifiedSyncTokenCHROMIUM(GLbyte* sync_token) override; void VerifySyncTokensCHROMIUM(GLbyte** sync_tokens, GLsizei count) override; void WaitSyncTokenCHROMIUM(const GLbyte* sync_token) override; void DrawBuffersEXT(GLsizei count, const GLenum* bufs) override;
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h index 189f277..39585093 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -2082,23 +2082,16 @@ gl_->LoseContextCHROMIUM(current, other); } -GLuint64 GLES2TraceImplementation::InsertFenceSyncCHROMIUM() { - TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::InsertFenceSyncCHROMIUM"); - return gl_->InsertFenceSyncCHROMIUM(); -} - -void GLES2TraceImplementation::GenSyncTokenCHROMIUM(GLuint64 fence_sync, - GLbyte* sync_token) { +void GLES2TraceImplementation::GenSyncTokenCHROMIUM(GLbyte* sync_token) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GenSyncTokenCHROMIUM"); - gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token); + gl_->GenSyncTokenCHROMIUM(sync_token); } void GLES2TraceImplementation::GenUnverifiedSyncTokenCHROMIUM( - GLuint64 fence_sync, GLbyte* sync_token) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GenUnverifiedSyncTokenCHROMIUM"); - gl_->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token); + gl_->GenUnverifiedSyncTokenCHROMIUM(sync_token); } void GLES2TraceImplementation::VerifySyncTokensCHROMIUM(GLbyte** sync_tokens,
diff --git a/gpu/command_buffer/client/gpu_control.h b/gpu/command_buffer/client/gpu_control.h index c2a7623..b9e6ccd 100644 --- a/gpu/command_buffer/client/gpu_control.h +++ b/gpu/command_buffer/client/gpu_control.h
@@ -95,16 +95,6 @@ // must be verified before sending a sync token across channel boundaries. virtual uint64_t GenerateFenceSyncRelease() = 0; - // Returns true if the fence sync is valid. - virtual bool IsFenceSyncRelease(uint64_t release) = 0; - - // Returns true if the client has flushed the fence sync. - virtual bool IsFenceSyncFlushed(uint64_t release) = 0; - - // Returns true if the service has received the fence sync. Used for verifying - // sync tokens. - virtual bool IsFenceSyncFlushReceived(uint64_t release) = 0; - // Returns true if the service has released (executed) the fence sync. Some // implementations may support calling this from any thread without holding // the lock provided by the client.
diff --git a/gpu/command_buffer/client/raster_implementation_gles.cc b/gpu/command_buffer/client/raster_implementation_gles.cc index 5fc46dcb..dd767ec7 100644 --- a/gpu/command_buffer/client/raster_implementation_gles.cc +++ b/gpu/command_buffer/client/raster_implementation_gles.cc
@@ -25,6 +25,10 @@ gl_->Finish(); } +void RasterImplementationGLES::Flush() { + gl_->Flush(); +} + void RasterImplementationGLES::ShallowFlushCHROMIUM() { gl_->ShallowFlushCHROMIUM(); } @@ -33,19 +37,13 @@ gl_->OrderingBarrierCHROMIUM(); } -GLuint64 RasterImplementationGLES::InsertFenceSyncCHROMIUM() { - return gl_->InsertFenceSyncCHROMIUM(); -} - -void RasterImplementationGLES::GenSyncTokenCHROMIUM(GLuint64 fence_sync, - GLbyte* sync_token) { - gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token); +void RasterImplementationGLES::GenSyncTokenCHROMIUM(GLbyte* sync_token) { + gl_->GenSyncTokenCHROMIUM(sync_token); } void RasterImplementationGLES::GenUnverifiedSyncTokenCHROMIUM( - GLuint64 fence_sync, GLbyte* sync_token) { - gl_->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token); + gl_->GenUnverifiedSyncTokenCHROMIUM(sync_token); } void RasterImplementationGLES::VerifySyncTokensCHROMIUM(GLbyte** sync_tokens, @@ -296,5 +294,22 @@ gl_->EndRasterCHROMIUM(); } +void RasterImplementationGLES::BeginGpuRaster() { + // TODO(alokp): Use a trace macro to push/pop markers. + // Using push/pop functions directly incurs cost to evaluate function + // arguments even when tracing is disabled. + gl_->TraceBeginCHROMIUM("BeginGpuRaster", "GpuRasterization"); +} + +void RasterImplementationGLES::EndGpuRaster() { + // Restore default GL unpack alignment. TextureUploader expects this. + gl_->PixelStorei(GL_UNPACK_ALIGNMENT, 4); + + // TODO(alokp): Use a trace macro to push/pop markers. + // Using push/pop functions directly incurs cost to evaluate function + // arguments even when tracing is disabled. + gl_->TraceEndCHROMIUM(); +} + } // namespace raster } // namespace gpu
diff --git a/gpu/command_buffer/client/raster_implementation_gles.h b/gpu/command_buffer/client/raster_implementation_gles.h index b046006..8f5c21a 100644 --- a/gpu/command_buffer/client/raster_implementation_gles.h +++ b/gpu/command_buffer/client/raster_implementation_gles.h
@@ -25,14 +25,13 @@ // Command buffer Flush / Finish. void Finish() override; + void Flush() override; void ShallowFlushCHROMIUM() override; void OrderingBarrierCHROMIUM() override; // SyncTokens. - GLuint64 InsertFenceSyncCHROMIUM() override; - void GenSyncTokenCHROMIUM(GLuint64 fence_sync, GLbyte* sync_token) override; - void GenUnverifiedSyncTokenCHROMIUM(GLuint64 fence_sync, - GLbyte* sync_token) override; + void GenSyncTokenCHROMIUM(GLbyte* sync_token) override; + void GenUnverifiedSyncTokenCHROMIUM(GLbyte* sync_token) override; void VerifySyncTokensCHROMIUM(GLbyte** sync_tokens, GLsizei count) override; void WaitSyncTokenCHROMIUM(const GLbyte* sync_token) override; @@ -147,6 +146,10 @@ GLfloat post_scale) override; void EndRasterCHROMIUM() override; + // Raster via GrContext. + void BeginGpuRaster() override; + void EndGpuRaster() override; + private: gles2::GLES2Interface* gl_; bool use_texture_storage_;
diff --git a/gpu/command_buffer/client/raster_implementation_gles_unittest.cc b/gpu/command_buffer/client/raster_implementation_gles_unittest.cc index ea4fa32..eba45b0 100644 --- a/gpu/command_buffer/client/raster_implementation_gles_unittest.cc +++ b/gpu/command_buffer/client/raster_implementation_gles_unittest.cc
@@ -23,6 +23,7 @@ using testing::_; using testing::Return; using testing::SetArgPointee; +using testing::StrEq; namespace gpu { namespace raster { @@ -31,15 +32,13 @@ public: // Command buffer Flush / Finish. MOCK_METHOD0(Finish, void()); + MOCK_METHOD0(Flush, void()); MOCK_METHOD0(ShallowFlushCHROMIUM, void()); MOCK_METHOD0(OrderingBarrierCHROMIUM, void()); // SyncTokens. - MOCK_METHOD0(InsertFenceSyncCHROMIUM, GLuint64()); - MOCK_METHOD2(GenSyncTokenCHROMIUM, - void(GLuint64 fence_sync, GLbyte* sync_token)); - MOCK_METHOD2(GenUnverifiedSyncTokenCHROMIUM, - void(GLuint64 fence_sync, GLbyte* sync_token)); + MOCK_METHOD1(GenSyncTokenCHROMIUM, void(GLbyte* sync_token)); + MOCK_METHOD1(GenUnverifiedSyncTokenCHROMIUM, void(GLbyte* sync_token)); MOCK_METHOD2(VerifySyncTokensCHROMIUM, void(GLbyte** sync_tokens, GLsizei count)); MOCK_METHOD1(WaitSyncTokenCHROMIUM, void(const GLbyte* sync_token)); @@ -154,6 +153,11 @@ GLfloat post_translate_y, GLfloat post_scale)); MOCK_METHOD0(EndRasterCHROMIUM, void()); + + MOCK_METHOD2(PixelStorei, void(GLenum pname, GLint param)); + MOCK_METHOD2(TraceBeginCHROMIUM, + void(const char* category_name, const char* trace_name)); + MOCK_METHOD0(TraceEndCHROMIUM, void()); }; class RasterImplementationGLESTest : public testing::Test { @@ -181,6 +185,11 @@ ri_->Finish(); } +TEST_F(RasterImplementationGLESTest, Flush) { + EXPECT_CALL(*gl_, Flush()).Times(1); + ri_->Flush(); +} + TEST_F(RasterImplementationGLESTest, ShallowFlushCHROMIUM) { EXPECT_CALL(*gl_, ShallowFlushCHROMIUM()).Times(1); ri_->ShallowFlushCHROMIUM(); @@ -191,30 +200,18 @@ ri_->OrderingBarrierCHROMIUM(); } -TEST_F(RasterImplementationGLESTest, InsertFenceSyncCHROMIUM) { - const GLuint64 kFenceSync = 0x123u; - GLuint64 fence_sync = 0; - - EXPECT_CALL(*gl_, InsertFenceSyncCHROMIUM()).WillOnce(Return(kFenceSync)); - fence_sync = ri_->InsertFenceSyncCHROMIUM(); - EXPECT_EQ(kFenceSync, fence_sync); -} - TEST_F(RasterImplementationGLESTest, GenSyncTokenCHROMIUM) { - const GLuint64 kFenceSync = 0x123u; GLbyte sync_token_data[GL_SYNC_TOKEN_SIZE_CHROMIUM] = {}; - EXPECT_CALL(*gl_, GenSyncTokenCHROMIUM(kFenceSync, sync_token_data)).Times(1); - ri_->GenSyncTokenCHROMIUM(kFenceSync, sync_token_data); + EXPECT_CALL(*gl_, GenSyncTokenCHROMIUM(sync_token_data)).Times(1); + ri_->GenSyncTokenCHROMIUM(sync_token_data); } TEST_F(RasterImplementationGLESTest, GenUnverifiedSyncTokenCHROMIUM) { - const GLuint64 kFenceSync = 0x123u; GLbyte sync_token_data[GL_SYNC_TOKEN_SIZE_CHROMIUM] = {}; - EXPECT_CALL(*gl_, GenUnverifiedSyncTokenCHROMIUM(kFenceSync, sync_token_data)) - .Times(1); - ri_->GenUnverifiedSyncTokenCHROMIUM(kFenceSync, sync_token_data); + EXPECT_CALL(*gl_, GenUnverifiedSyncTokenCHROMIUM(sync_token_data)).Times(1); + ri_->GenUnverifiedSyncTokenCHROMIUM(sync_token_data); } TEST_F(RasterImplementationGLESTest, VerifySyncTokensCHROMIUM) { @@ -647,5 +644,18 @@ ri_->EndRasterCHROMIUM(); } +TEST_F(RasterImplementationGLESTest, BeginGpuRaster) { + EXPECT_CALL(*gl_, TraceBeginCHROMIUM(StrEq("BeginGpuRaster"), + StrEq("GpuRasterization"))) + .Times(1); + ri_->BeginGpuRaster(); +} + +TEST_F(RasterImplementationGLESTest, EndGpuRaster) { + EXPECT_CALL(*gl_, PixelStorei(GL_UNPACK_ALIGNMENT, 4)).Times(1); + EXPECT_CALL(*gl_, TraceEndCHROMIUM()).Times(1); + ri_->EndGpuRaster(); +} + } // namespace raster } // namespace gpu
diff --git a/gpu/command_buffer/client/raster_interface.h b/gpu/command_buffer/client/raster_interface.h index 2adf81c..95ebcd0 100644 --- a/gpu/command_buffer/client/raster_interface.h +++ b/gpu/command_buffer/client/raster_interface.h
@@ -28,15 +28,13 @@ // Command buffer Flush / Finish. virtual void Finish() = 0; + virtual void Flush() = 0; virtual void ShallowFlushCHROMIUM() = 0; virtual void OrderingBarrierCHROMIUM() = 0; // SyncTokens. - virtual GLuint64 InsertFenceSyncCHROMIUM() = 0; - virtual void GenSyncTokenCHROMIUM(GLuint64 fence_sync, - GLbyte* sync_token) = 0; - virtual void GenUnverifiedSyncTokenCHROMIUM(GLuint64 fence_sync, - GLbyte* sync_token) = 0; + virtual void GenSyncTokenCHROMIUM(GLbyte* sync_token) = 0; + virtual void GenUnverifiedSyncTokenCHROMIUM(GLbyte* sync_token) = 0; virtual void VerifySyncTokensCHROMIUM(GLbyte** sync_tokens, GLsizei count) = 0; virtual void WaitSyncTokenCHROMIUM(const GLbyte* sync_token) = 0; @@ -153,6 +151,10 @@ GLfloat post_translate_y, GLfloat post_scale) = 0; virtual void EndRasterCHROMIUM() = 0; + + // Raster via GrContext. + virtual void BeginGpuRaster() = 0; + virtual void EndGpuRaster() = 0; }; } // namespace raster
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt index 900d0b72..b878b92 100644 --- a/gpu/command_buffer/cmd_buffer_functions.txt +++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -298,8 +298,8 @@ GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenumFramebufferTarget target, GLsizei count, const GLenum* attachments); GL_APICALL void GL_APIENTRY glLoseContextCHROMIUM (GLenumResetStatus current, GLenumResetStatus other); GL_APICALL GLuint64 GL_APIENTRY glInsertFenceSyncCHROMIUM (void); -GL_APICALL void GL_APIENTRY glGenSyncTokenCHROMIUM (GLuint64 fence_sync, GLbyte* sync_token); -GL_APICALL void GL_APIENTRY glGenUnverifiedSyncTokenCHROMIUM (GLuint64 fence_sync, GLbyte* sync_token); +GL_APICALL void GL_APIENTRY glGenSyncTokenCHROMIUM (GLbyte* sync_token); +GL_APICALL void GL_APIENTRY glGenUnverifiedSyncTokenCHROMIUM (GLbyte* sync_token); GL_APICALL void GL_APIENTRY glVerifySyncTokensCHROMIUM (GLbyte** sync_tokens, GLsizei count); GL_APICALL void GL_APIENTRY glWaitSyncTokenCHROMIUM (const GLbyte* sync_token); GL_APICALL void GL_APIENTRY glDrawBuffersEXT (GLsizei count, const GLenum* bufs);
diff --git a/gpu/command_buffer/tests/decoder_perftest.cc b/gpu/command_buffer/tests/decoder_perftest.cc index 958802f0..a5ceab86 100644 --- a/gpu/command_buffer/tests/decoder_perftest.cc +++ b/gpu/command_buffer/tests/decoder_perftest.cc
@@ -302,21 +302,6 @@ return 0; } - bool IsFenceSyncRelease(uint64_t release) override { - NOTIMPLEMENTED(); - return true; - } - - bool IsFenceSyncFlushed(uint64_t release) override { - NOTIMPLEMENTED(); - return true; - } - - bool IsFenceSyncFlushReceived(uint64_t release) override { - NOTIMPLEMENTED(); - return true; - } - bool IsFenceSyncReleased(uint64_t release) override { NOTIMPLEMENTED(); return true;
diff --git a/gpu/command_buffer/tests/gl_fence_sync_unittest.cc b/gpu/command_buffer/tests/gl_fence_sync_unittest.cc index a9b68d3..5695997 100644 --- a/gpu/command_buffer/tests/gl_fence_sync_unittest.cc +++ b/gpu/command_buffer/tests/gl_fence_sync_unittest.cc
@@ -46,10 +46,9 @@ TEST_F(GLFenceSyncTest, SimpleReleaseWait) { gl1_.MakeCurrent(); - const GLuint64 fence_sync = glInsertFenceSyncCHROMIUM(); SyncToken sync_token; glFlush(); - glGenSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + glGenSyncTokenCHROMIUM(sync_token.GetData()); ASSERT_TRUE(GL_NO_ERROR == glGetError()); // Make sure it is actually released. @@ -70,9 +69,8 @@ // Pause the command buffer so the fence sync does not immediately trigger. gl1_.SetCommandsPaused(true); - const GLuint64 fence_sync = glInsertFenceSyncCHROMIUM(); SyncToken sync_token; - glGenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + glGenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); glFlush(); ASSERT_TRUE(sync_token.HasData());
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc index af60986..94498fb 100644 --- a/gpu/command_buffer/tests/gl_manager.cc +++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -555,18 +555,6 @@ return next_fence_sync_release_++; } -bool GLManager::IsFenceSyncRelease(uint64_t release) { - return release > 0 && release < next_fence_sync_release_; -} - -bool GLManager::IsFenceSyncFlushed(uint64_t release) { - return IsFenceSyncRelease(release); -} - -bool GLManager::IsFenceSyncFlushReceived(uint64_t release) { - return IsFenceSyncRelease(release); -} - bool GLManager::IsFenceSyncReleased(uint64_t release) { return release <= command_buffer_->GetLastState().release_count; }
diff --git a/gpu/command_buffer/tests/gl_manager.h b/gpu/command_buffer/tests/gl_manager.h index 4527e62..44ef18b 100644 --- a/gpu/command_buffer/tests/gl_manager.h +++ b/gpu/command_buffer/tests/gl_manager.h
@@ -147,9 +147,6 @@ CommandBufferId GetCommandBufferID() const override; void FlushPendingWork() override; uint64_t GenerateFenceSyncRelease() override; - bool IsFenceSyncRelease(uint64_t release) override; - bool IsFenceSyncFlushed(uint64_t release) override; - bool IsFenceSyncFlushReceived(uint64_t release) override; bool IsFenceSyncReleased(uint64_t release) override; void SignalSyncToken(const gpu::SyncToken& sync_token, const base::Closure& callback) override;
diff --git a/gpu/gles2_conform_support/egl/context.cc b/gpu/gles2_conform_support/egl/context.cc index e4cd97d4..329934c2 100644 --- a/gpu/gles2_conform_support/egl/context.cc +++ b/gpu/gles2_conform_support/egl/context.cc
@@ -221,18 +221,6 @@ return display_->GenerateFenceSyncRelease(); } -bool Context::IsFenceSyncRelease(uint64_t release) { - return display_->IsFenceSyncRelease(release); -} - -bool Context::IsFenceSyncFlushed(uint64_t release) { - return display_->IsFenceSyncFlushed(release); -} - -bool Context::IsFenceSyncFlushReceived(uint64_t release) { - return display_->IsFenceSyncFlushReceived(release); -} - bool Context::IsFenceSyncReleased(uint64_t release) { NOTIMPLEMENTED(); return false;
diff --git a/gpu/gles2_conform_support/egl/context.h b/gpu/gles2_conform_support/egl/context.h index 1401cca..d9237ef 100644 --- a/gpu/gles2_conform_support/egl/context.h +++ b/gpu/gles2_conform_support/egl/context.h
@@ -76,9 +76,6 @@ gpu::CommandBufferId GetCommandBufferID() const override; void FlushPendingWork() override; uint64_t GenerateFenceSyncRelease() override; - bool IsFenceSyncRelease(uint64_t release) override; - bool IsFenceSyncFlushed(uint64_t release) override; - bool IsFenceSyncFlushReceived(uint64_t release) override; bool IsFenceSyncReleased(uint64_t release) override; void SignalSyncToken(const gpu::SyncToken& sync_token, const base::Closure& callback) override;
diff --git a/gpu/gles2_conform_support/egl/display.cc b/gpu/gles2_conform_support/egl/display.cc index a7959ff..5e954369 100644 --- a/gpu/gles2_conform_support/egl/display.cc +++ b/gpu/gles2_conform_support/egl/display.cc
@@ -355,19 +355,6 @@ return next_fence_sync_release_++; } -bool Display::IsFenceSyncRelease(uint64_t release) { - base::AutoLock auto_lock(lock_); - return release > 0 && release < next_fence_sync_release_; -} - -bool Display::IsFenceSyncFlushed(uint64_t release) { - return IsFenceSyncRelease(release); -} - -bool Display::IsFenceSyncFlushReceived(uint64_t release) { - return IsFenceSyncRelease(release); -} - void Display::InitializeConfigsIfNeeded() { lock_.AssertAcquired(); if (!configs_[0]) {
diff --git a/gpu/gles2_conform_support/egl/display.h b/gpu/gles2_conform_support/egl/display.h index 5ac6e46f..cac60502 100644 --- a/gpu/gles2_conform_support/egl/display.h +++ b/gpu/gles2_conform_support/egl/display.h
@@ -77,9 +77,6 @@ EGLBoolean MakeCurrent(ThreadState*, EGLSurface, EGLSurface, EGLContext); uint64_t GenerateFenceSyncRelease(); - bool IsFenceSyncRelease(uint64_t release); - bool IsFenceSyncFlushed(uint64_t release); - bool IsFenceSyncFlushReceived(uint64_t release); private: void InitializeConfigsIfNeeded();
diff --git a/gpu/ipc/client/command_buffer_proxy_impl.cc b/gpu/ipc/client/command_buffer_proxy_impl.cc index 311adfe..6f8385a 100644 --- a/gpu/ipc/client/command_buffer_proxy_impl.cc +++ b/gpu/ipc/client/command_buffer_proxy_impl.cc
@@ -566,27 +566,6 @@ return next_fence_sync_release_++; } -bool CommandBufferProxyImpl::IsFenceSyncRelease(uint64_t release) { - CheckLock(); - return release && release < next_fence_sync_release_; -} - -bool CommandBufferProxyImpl::IsFenceSyncFlushed(uint64_t release) { - CheckLock(); - return release && release <= flushed_fence_sync_release_; -} - -bool CommandBufferProxyImpl::IsFenceSyncFlushReceived(uint64_t release) { - CheckLock(); - if (release > verified_fence_sync_release_) { - // Don't send messages once disconnected. - if (!disconnected_) - channel_->VerifyFlush(last_flush_id_); - verified_fence_sync_release_ = flushed_fence_sync_release_; - } - return release && release <= verified_fence_sync_release_; -} - // This can be called from any thread without holding |lock_|. Use a thread-safe // non-error throwing variant of TryUpdateState for this. bool CommandBufferProxyImpl::IsFenceSyncReleased(uint64_t release) {
diff --git a/gpu/ipc/client/command_buffer_proxy_impl.h b/gpu/ipc/client/command_buffer_proxy_impl.h index 0b7c785..664e9b31b 100644 --- a/gpu/ipc/client/command_buffer_proxy_impl.h +++ b/gpu/ipc/client/command_buffer_proxy_impl.h
@@ -130,9 +130,6 @@ gpu::CommandBufferId GetCommandBufferID() const override; void FlushPendingWork() override; uint64_t GenerateFenceSyncRelease() override; - bool IsFenceSyncRelease(uint64_t release) override; - bool IsFenceSyncFlushed(uint64_t release) override; - bool IsFenceSyncFlushReceived(uint64_t release) override; bool IsFenceSyncReleased(uint64_t release) override; void SignalSyncToken(const gpu::SyncToken& sync_token, const base::Closure& callback) override;
diff --git a/gpu/ipc/client/gpu_context_tests.h b/gpu/ipc/client/gpu_context_tests.h index 88060b7a..3d08dd2 100644 --- a/gpu/ipc/client/gpu_context_tests.h +++ b/gpu/ipc/client/gpu_context_tests.h
@@ -51,11 +51,8 @@ return; #endif - const GLuint64 fence_sync = gl_->InsertFenceSyncCHROMIUM(); - gl_->ShallowFlushCHROMIUM(); - gpu::SyncToken sync_token; - gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + gl_->GenSyncTokenCHROMIUM(sync_token.GetData()); TestSignalSyncToken(sync_token); };
diff --git a/gpu/ipc/in_process_command_buffer.cc b/gpu/ipc/in_process_command_buffer.cc index 46f1078..ba565b1 100644 --- a/gpu/ipc/in_process_command_buffer.cc +++ b/gpu/ipc/in_process_command_buffer.cc
@@ -1079,18 +1079,6 @@ return next_fence_sync_release_++; } -bool InProcessCommandBuffer::IsFenceSyncRelease(uint64_t release) { - return release != 0 && release < next_fence_sync_release_; -} - -bool InProcessCommandBuffer::IsFenceSyncFlushed(uint64_t release) { - return release <= flushed_fence_sync_release_; -} - -bool InProcessCommandBuffer::IsFenceSyncFlushReceived(uint64_t release) { - return IsFenceSyncFlushed(release); -} - bool InProcessCommandBuffer::IsFenceSyncReleased(uint64_t release) { return release <= GetLastState().release_count; }
diff --git a/gpu/ipc/in_process_command_buffer.h b/gpu/ipc/in_process_command_buffer.h index a2b961f..62eb96b9f 100644 --- a/gpu/ipc/in_process_command_buffer.h +++ b/gpu/ipc/in_process_command_buffer.h
@@ -141,9 +141,6 @@ CommandBufferId GetCommandBufferID() const override; void FlushPendingWork() override; uint64_t GenerateFenceSyncRelease() override; - bool IsFenceSyncRelease(uint64_t release) override; - bool IsFenceSyncFlushed(uint64_t release) override; - bool IsFenceSyncFlushReceived(uint64_t release) override; bool IsFenceSyncReleased(uint64_t release) override; void SignalSyncToken(const SyncToken& sync_token, const base::Closure& callback) override;
diff --git a/ios/chrome/app/strings/ios_chromium_strings.grd b/ios/chrome/app/strings/ios_chromium_strings.grd index 51f798a5..6797f7c4 100644 --- a/ios/chrome/app/strings/ios_chromium_strings.grd +++ b/ios/chrome/app/strings/ios_chromium_strings.grd
@@ -198,9 +198,6 @@ <message name="IDS_IOS_OPTIONS_ACCOUNTS_SIGNOUT" desc="Title of the button to sign out of Chromium [iOS only] [60em]"> Sign out of Chromium </message> - <message name="IDS_IOS_OPTIONS_ENABLE_PHYSICAL_WEB_DETAILS" desc="The detailed description of an option to enable scanning for nearby devices broadcasting URLs."> - Discover web pages sent by nearby objects. When Bluetooth is turned on, Chromium can gather web pages associated with objects around you and send them anonymously to Google to find the most useful ones. <ph name="BEGIN_LINK">BEGIN_LINK</ph>Learn more<ph name="END_LINK">END_LINK</ph> - </message> <message name="IDS_IOS_OPTIONS_IMPORT_DATA_TITLE_SIGNIN" desc="The title of the Import Data settings screen when signing in. [30em]"> Sign in to Chromium </message>
diff --git a/ios/chrome/app/strings/ios_google_chrome_strings.grd b/ios/chrome/app/strings/ios_google_chrome_strings.grd index f91821c..73ec0d9 100644 --- a/ios/chrome/app/strings/ios_google_chrome_strings.grd +++ b/ios/chrome/app/strings/ios_google_chrome_strings.grd
@@ -198,9 +198,6 @@ <message name="IDS_IOS_OPTIONS_ACCOUNTS_SIGNOUT" desc="Title of the button to sign out of Chrome [iOS only] [60em]"> Sign out of Chrome </message> - <message name="IDS_IOS_OPTIONS_ENABLE_PHYSICAL_WEB_DETAILS" desc="The detailed description of an option to enable scanning for nearby devices broadcasting URLs."> - Discover web pages sent by nearby objects. When Bluetooth is turned on, Chrome can gather web pages associated with objects around you and send them anonymously to Google to find the most useful ones. <ph name="BEGIN_LINK">BEGIN_LINK</ph>Learn more<ph name="END_LINK">END_LINK</ph> - </message> <message name="IDS_IOS_OPTIONS_IMPORT_DATA_TITLE_SIGNIN" desc="The title of the Import Data settings screen when signing in. [30em]"> Sign in to Chrome </message>
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index a3a18e3..a33ec14f 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -808,9 +808,6 @@ Handoff must also be enabled in the General section of Settings, and your devices must use the same iCloud account. </message> - <message name="IDS_IOS_OPTIONS_ENABLE_PHYSICAL_WEB" desc="Title for the option to enable scanning for nearby devices broadcasting URLs. [Length: 20em] [iOS only]"> - Physical Web - </message> <message name="IDS_IOS_OPTIONS_GENERAL_TAB_LABEL" desc="The title of the Basics section of the Settings page. [iOS only]" meaning="The title of the Basics section of the Settings page."> Basics </message>
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn index 6de98188..9bf0ec57 100644 --- a/ios/chrome/browser/BUILD.gn +++ b/ios/chrome/browser/BUILD.gn
@@ -192,7 +192,6 @@ "//ios/chrome/browser/metrics", "//ios/chrome/browser/net", "//ios/chrome/browser/open_from_clipboard", - "//ios/chrome/browser/physical_web", "//ios/chrome/browser/prefs", "//ios/chrome/browser/prefs:browser_prefs", "//ios/chrome/browser/services/gcm",
diff --git a/ios/chrome/browser/application_context.h b/ios/chrome/browser/application_context.h index 9f91990..908d181 100644 --- a/ios/chrome/browser/application_context.h +++ b/ios/chrome/browser/application_context.h
@@ -41,10 +41,6 @@ class NetworkTimeTracker; } -namespace physical_web { -class PhysicalWebDataSource; -} - namespace rappor { class RapporServiceImpl; } @@ -127,9 +123,6 @@ virtual component_updater::ComponentUpdateService* GetComponentUpdateService() = 0; - // Gets the PhysicalWebDataSource. - virtual physical_web::PhysicalWebDataSource* GetPhysicalWebDataSource() = 0; - protected: // Sets the global ApplicationContext instance. static void SetApplicationContext(ApplicationContext* context);
diff --git a/ios/chrome/browser/application_context_impl.cc b/ios/chrome/browser/application_context_impl.cc index 95741de..7b5e5fc 100644 --- a/ios/chrome/browser/application_context_impl.cc +++ b/ios/chrome/browser/application_context_impl.cc
@@ -26,7 +26,6 @@ #include "components/metrics_services_manager/metrics_services_manager.h" #include "components/net_log/chrome_net_log.h" #include "components/network_time/network_time_tracker.h" -#include "components/physical_web/data_source/physical_web_data_source.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "components/translate/core/browser/translate_download_manager.h" @@ -41,7 +40,6 @@ #include "ios/chrome/browser/history/history_service_factory.h" #include "ios/chrome/browser/ios_chrome_io_thread.h" #include "ios/chrome/browser/metrics/ios_chrome_metrics_services_manager_client.h" -#include "ios/chrome/browser/physical_web/create_physical_web_data_source.h" #include "ios/chrome/browser/pref_names.h" #include "ios/chrome/browser/prefs/browser_prefs.h" #include "ios/chrome/browser/prefs/ios_chrome_pref_service_factory.h" @@ -284,17 +282,6 @@ return component_updater_.get(); } -physical_web::PhysicalWebDataSource* -ApplicationContextImpl::GetPhysicalWebDataSource() { - DCHECK(thread_checker_.CalledOnValidThread()); - if (!physical_web_data_source_) { - physical_web_data_source_ = - CreateIOSChromePhysicalWebDataSource(GetLocalState()); - DCHECK(physical_web_data_source_); - } - return physical_web_data_source_.get(); -} - void ApplicationContextImpl::SetApplicationLocale(const std::string& locale) { DCHECK(thread_checker_.CalledOnValidThread()); application_locale_ = locale;
diff --git a/ios/chrome/browser/application_context_impl.h b/ios/chrome/browser/application_context_impl.h index 8874206..703c92e 100644 --- a/ios/chrome/browser/application_context_impl.h +++ b/ios/chrome/browser/application_context_impl.h
@@ -59,7 +59,6 @@ gcm::GCMDriver* GetGCMDriver() override; component_updater::ComponentUpdateService* GetComponentUpdateService() override; - physical_web::PhysicalWebDataSource* GetPhysicalWebDataSource() override; private: // Sets the locale used by the application. @@ -82,8 +81,6 @@ std::unique_ptr<component_updater::ComponentUpdateService> component_updater_; std::unique_ptr<ios::ChromeBrowserStateManager> chrome_browser_state_manager_; std::string application_locale_; - std::unique_ptr<physical_web::PhysicalWebDataSource> - physical_web_data_source_; // Sequenced task runner for local state related I/O tasks. const scoped_refptr<base::SequencedTaskRunner> local_state_task_runner_;
diff --git a/ios/chrome/browser/autocomplete/autocomplete_provider_client_impl.cc b/ios/chrome/browser/autocomplete/autocomplete_provider_client_impl.cc index 5e582b76..d8e104f 100644 --- a/ios/chrome/browser/autocomplete/autocomplete_provider_client_impl.cc +++ b/ios/chrome/browser/autocomplete/autocomplete_provider_client_impl.cc
@@ -114,7 +114,7 @@ physical_web::PhysicalWebDataSource* AutocompleteProviderClientImpl::GetPhysicalWebDataSource() { - return GetApplicationContext()->GetPhysicalWebDataSource(); + return nullptr; } std::string AutocompleteProviderClientImpl::GetAcceptLanguages() const {
diff --git a/ios/chrome/browser/chrome_url_constants.cc b/ios/chrome/browser/chrome_url_constants.cc index cb55f052..55e33d1 100644 --- a/ios/chrome/browser/chrome_url_constants.cc +++ b/ios/chrome/browser/chrome_url_constants.cc
@@ -18,7 +18,6 @@ const char kChromeUINewTabURL[] = "chrome://newtab/"; const char kChromeUINTPTilesInternalsURL[] = "chrome://ntp-tiles-internals/"; const char kChromeUIOfflineURL[] = "chrome://offline/"; -const char kChromeUIPhysicalWebURL[] = "chrome://physical-web/"; const char kChromeUISettingsURL[] = "chrome://settings/"; const char kChromeUISuggestionsURL[] = "chrome://suggestions/"; const char kChromeUITermsURL[] = "chrome://terms/"; @@ -42,7 +41,6 @@ const char kChromeUIOmahaHost[] = "omaha"; const char kChromeUIPasswordManagerInternalsHost[] = "password-manager-internals"; -const char kChromeUIPhysicalWebHost[] = "physical-web"; const char kChromeUIPolicyHost[] = "policy"; const char kChromeUISignInInternalsHost[] = "signin-internals"; const char kChromeUISuggestionsHost[] = "suggestions"; @@ -66,7 +64,6 @@ kChromeUISignInInternalsHost, kChromeUISuggestionsHost, kChromeUISyncInternalsHost, - kChromeUIPhysicalWebHost, kChromeUITermsHost, kChromeUIVersionHost, }; @@ -86,9 +83,6 @@ const char kDoNotTrackLearnMoreURL[] = "https://support.google.com/chrome/answer/2942429?p=mobile_do_not_track"; -const char kPhysicalWebLearnMoreURL[] = - "https://support.google.com/chrome/answer/6239299?p=physical_web"; - const char kSyncEncryptionHelpURL[] = "https://support.google.com/chrome/answer/1181035?p=settings_encryption";
diff --git a/ios/chrome/browser/chrome_url_constants.h b/ios/chrome/browser/chrome_url_constants.h index 5103d16..a37baf3 100644 --- a/ios/chrome/browser/chrome_url_constants.h +++ b/ios/chrome/browser/chrome_url_constants.h
@@ -28,7 +28,6 @@ extern const char kChromeUINewTabURL[]; extern const char kChromeUINTPTilesInternalsURL[]; extern const char kChromeUIOfflineURL[]; -extern const char kChromeUIPhysicalWebURL[]; extern const char kChromeUIPopularSitesInternalsURL[]; extern const char kChromeUISettingsURL[]; extern const char kChromeUISuggestionsURL[]; @@ -53,7 +52,6 @@ extern const char kChromeUIOfflineHost[]; extern const char kChromeUIOmahaHost[]; extern const char kChromeUIPasswordManagerInternalsHost[]; -extern const char kChromeUIPhysicalWebHost[]; extern const char kChromeUIPopularSitesInternalsHost[]; extern const char kChromeUIPolicyHost[]; extern const char kChromeUISignInInternalsHost[]; @@ -81,9 +79,6 @@ // "Learn more" URL for the "Do not track" setting in the privacy section. extern const char kDoNotTrackLearnMoreURL[]; -// "Learn more" URL for the Physical Web setting in the privacy section. -extern const char kPhysicalWebLearnMoreURL[]; - // The URL for the "Learn more" page on sync encryption. extern const char kSyncEncryptionHelpURL[];
diff --git a/ios/chrome/browser/experimental_flags.h b/ios/chrome/browser/experimental_flags.h index ab30dbb..d0ab2cb4 100644 --- a/ios/chrome/browser/experimental_flags.h +++ b/ios/chrome/browser/experimental_flags.h
@@ -51,9 +51,6 @@ // Whether the page icon for downgraded HTTPS is enabled. bool IsPageIconForDowngradedHTTPSEnabled(); -// Whether the Physical Web feature is enabled. -bool IsPhysicalWebEnabled(); - // Whether startup crash is enabled. bool IsStartupCrashEnabled();
diff --git a/ios/chrome/browser/experimental_flags.mm b/ios/chrome/browser/experimental_flags.mm index c1c254d..bcb34bf9 100644 --- a/ios/chrome/browser/experimental_flags.mm +++ b/ios/chrome/browser/experimental_flags.mm
@@ -111,12 +111,6 @@ base::CompareCase::INSENSITIVE_ASCII); } -bool IsPhysicalWebEnabled() { - // TODO(crbug.com/760104): Remove this function and its associated code. - // Either by replacing it with a base::Feature or by removing all its uses. - return false; -} - bool IsStartupCrashEnabled() { return [[NSUserDefaults standardUserDefaults] boolForKey:kEnableStartupCrash]; }
diff --git a/ios/chrome/browser/passwords/resources/password_controller.js b/ios/chrome/browser/passwords/resources/password_controller.js index 32fb84e4..28993a3 100644 --- a/ios/chrome/browser/passwords/resources/password_controller.js +++ b/ios/chrome/browser/passwords/resources/password_controller.js
@@ -29,7 +29,7 @@ __gCrWeb['findPasswordForms'] = function() { var formDataList = []; if (hasPasswordField_(window)) { - __gCrWeb.getPasswordFormDataList(formDataList, window); + getPasswordFormDataList_(formDataList, window); } return __gCrWeb.stringify(formDataList); }; @@ -257,7 +257,7 @@ * @param {Window} win A window (or frame) in which the function should * look for password forms. */ - __gCrWeb.getPasswordFormDataList = function(formDataList, win) { + var getPasswordFormDataList_ = function(formDataList, win) { var doc = win.document; var forms = doc.forms; for (var i = 0; i < forms.length; i++) { @@ -271,7 +271,7 @@ // Recursively invoke for all iframes. var frames = getSameOriginFrames_(win); for (var i = 0; i < frames.length; i++) { - __gCrWeb.getPasswordFormDataList(formDataList, frames[i]); + getPasswordFormDataList_(formDataList, frames[i]); } }; @@ -287,10 +287,6 @@ var passwords = []; var firstPasswordIndex = 0; for (var j = 0; j < inputs.length; j++) { - // TODO(dplotnikov): figure out a way to identify the activated - // submit, which is the button that the user has already hit - // before this code is called. - var input = inputs[j]; fields.push({
diff --git a/ios/chrome/browser/physical_web/BUILD.gn b/ios/chrome/browser/physical_web/BUILD.gn deleted file mode 100644 index 3257f057..0000000 --- a/ios/chrome/browser/physical_web/BUILD.gn +++ /dev/null
@@ -1,34 +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. - -source_set("physical_web") { - configs += [ "//build/config/compiler:enable_arc" ] - sources = [ - "create_physical_web_data_source.h", - "create_physical_web_data_source.mm", - "ios_chrome_physical_web_data_source.h", - "ios_chrome_physical_web_data_source.mm", - "physical_web_constants.h", - "physical_web_initial_state_recorder.h", - "physical_web_initial_state_recorder.mm", - "physical_web_prefs_registration.cc", - "physical_web_prefs_registration.h", - "start_physical_web_discovery.h", - "start_physical_web_discovery.mm", - ] - deps = [ - "//base", - "//components/physical_web/data_source", - "//components/pref_registry", - "//components/prefs", - "//components/search_engines", - "//ios/chrome/browser", - "//ios/chrome/browser/browser_state", - "//ios/chrome/browser/geolocation", - "//ios/chrome/browser/search_engines", - "//ios/chrome/common/physical_web", - "//url", - ] - libs = [ "CoreLocation.framework" ] -}
diff --git a/ios/chrome/browser/physical_web/create_physical_web_data_source.h b/ios/chrome/browser/physical_web/create_physical_web_data_source.h deleted file mode 100644 index 4646959..0000000 --- a/ios/chrome/browser/physical_web/create_physical_web_data_source.h +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_PHYSICAL_WEB_CREATE_PHYSICAL_WEB_DATA_SOURCE_H_ -#define IOS_CHROME_BROWSER_PHYSICAL_WEB_CREATE_PHYSICAL_WEB_DATA_SOURCE_H_ - -#include <memory> - -namespace physical_web { -class PhysicalWebDataSource; -} -class PrefService; - -// Creates a new instance of IOSChromePhysicalWebDataSource. The returned object -// is fully initialized and can be registered as global singleton. -std::unique_ptr<physical_web::PhysicalWebDataSource> -CreateIOSChromePhysicalWebDataSource(PrefService* prefService); - -#endif // IOS_CHROME_BROWSER_PHYSICAL_WEB_CREATE_PHYSICAL_WEB_DATA_SOURCE_H_
diff --git a/ios/chrome/browser/physical_web/create_physical_web_data_source.mm b/ios/chrome/browser/physical_web/create_physical_web_data_source.mm deleted file mode 100644 index df210f7..0000000 --- a/ios/chrome/browser/physical_web/create_physical_web_data_source.mm +++ /dev/null
@@ -1,17 +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 "ios/chrome/browser/physical_web/create_physical_web_data_source.h" - -#include "base/memory/ptr_util.h" -#import "ios/chrome/browser/physical_web/ios_chrome_physical_web_data_source.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -std::unique_ptr<physical_web::PhysicalWebDataSource> -CreateIOSChromePhysicalWebDataSource(PrefService* prefService) { - return base::MakeUnique<IOSChromePhysicalWebDataSource>(prefService); -}
diff --git a/ios/chrome/browser/physical_web/ios_chrome_physical_web_data_source.h b/ios/chrome/browser/physical_web/ios_chrome_physical_web_data_source.h deleted file mode 100644 index 223ba7e..0000000 --- a/ios/chrome/browser/physical_web/ios_chrome_physical_web_data_source.h +++ /dev/null
@@ -1,49 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_PHYSICAL_WEB_IOS_CHROME_PHYSICAL_WEB_DATA_SOURCE_H_ -#define IOS_CHROME_BROWSER_PHYSICAL_WEB_IOS_CHROME_PHYSICAL_WEB_DATA_SOURCE_H_ - -#include "base/macros.h" -#import "base/mac/scoped_nsobject.h" -#include "components/physical_web/data_source/physical_web_data_source_impl.h" - -class PrefService; - -@class PhysicalWebScanner; -@class PhysicalWebInitialStateRecorder; - -// iOS implementation of PhysicalWebDataSource -class IOSChromePhysicalWebDataSource - : public physical_web::PhysicalWebDataSourceImpl { - public: - IOSChromePhysicalWebDataSource(PrefService* pref_service); - ~IOSChromePhysicalWebDataSource() override; - - // Starts scanning for Physical Web URLs. If |network_request_enabled| is - // true, discovered URLs will be sent to a resolution service. - void StartDiscovery(bool network_request_enabled) override; - - // Stops scanning for Physical Web URLs and clears cached URL content. - void StopDiscovery() override; - - // Returns a list of resolved URLs and associated page metadata. If network - // requests are disabled, the list will be empty. - std::unique_ptr<physical_web::MetadataList> GetMetadataList() override; - - // Returns boolean |true| if network requests are disabled and there are one - // or more discovered URLs that have not been sent to the resolution service. - bool HasUnresolvedDiscoveries() override; - - private: - // Scanner for nearby Physical Web URL devices. - base::scoped_nsobject<PhysicalWebScanner> scanner_; - - // Utility for fetching initial application state for logging purposes. - base::scoped_nsobject<PhysicalWebInitialStateRecorder> initialStateRecorder_; - - DISALLOW_COPY_AND_ASSIGN(IOSChromePhysicalWebDataSource); -}; - -#endif // IOS_CHROME_BROWSER_PHYSICAL_WEB_IOS_CHROME_PHYSICAL_WEB_DATA_SOURCE_H_
diff --git a/ios/chrome/browser/physical_web/ios_chrome_physical_web_data_source.mm b/ios/chrome/browser/physical_web/ios_chrome_physical_web_data_source.mm deleted file mode 100644 index 2366193..0000000 --- a/ios/chrome/browser/physical_web/ios_chrome_physical_web_data_source.mm +++ /dev/null
@@ -1,61 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/physical_web/ios_chrome_physical_web_data_source.h" - -#include "base/memory/ptr_util.h" -#import "ios/chrome/browser/physical_web/physical_web_initial_state_recorder.h" -#import "ios/chrome/common/physical_web/physical_web_scanner.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -IOSChromePhysicalWebDataSource::IOSChromePhysicalWebDataSource( - PrefService* pref_service) { - initialStateRecorder_.reset([[PhysicalWebInitialStateRecorder alloc] - initWithPrefService:pref_service]); - [initialStateRecorder_ collectAndRecordState]; -} - -IOSChromePhysicalWebDataSource::~IOSChromePhysicalWebDataSource() { - [initialStateRecorder_ invalidate]; - StopDiscovery(); -} - -void IOSChromePhysicalWebDataSource::StartDiscovery( - bool network_request_enabled) { - // If there are unresolved beacons it means the scanner is started but does - // not have network requests enabled. In this case we should avoid recreating - // the scanner as it would clear the cache of nearby beacons. - if (network_request_enabled && HasUnresolvedDiscoveries()) { - [scanner_ setNetworkRequestEnabled:YES]; - return; - } - - [scanner_ stop]; - scanner_.reset([[PhysicalWebScanner alloc] initWithDelegate:nil]); - - // Configure the scanner to notify us when a URL is no longer nearby. - [scanner_ setOnLostDetectionEnabled:YES]; - [scanner_ setNetworkRequestEnabled:network_request_enabled]; - [scanner_ start]; -} - -void IOSChromePhysicalWebDataSource::StopDiscovery() { - [scanner_ stop]; - scanner_.reset(); -} - -std::unique_ptr<physical_web::MetadataList> -IOSChromePhysicalWebDataSource::GetMetadataList() { - if (!scanner_) { - return base::MakeUnique<physical_web::MetadataList>(); - } - return [scanner_ metadataList]; -} - -bool IOSChromePhysicalWebDataSource::HasUnresolvedDiscoveries() { - return [scanner_ unresolvedBeaconsCount] > 0; -}
diff --git a/ios/chrome/browser/physical_web/physical_web_constants.h b/ios/chrome/browser/physical_web/physical_web_constants.h deleted file mode 100644 index 1c77c52..0000000 --- a/ios/chrome/browser/physical_web/physical_web_constants.h +++ /dev/null
@@ -1,17 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_PHYSICAL_WEB_PHYSICAL_WEB_CONSTANTS_H_ -#define IOS_CHROME_BROWSER_PHYSICAL_WEB_PHYSICAL_WEB_CONSTANTS_H_ - -namespace physical_web { - -enum PhysicalWebState { - kPhysicalWebOff = 0, - kPhysicalWebOn = 1, - kPhysicalWebOnboarding = 2, -}; -} - -#endif // IOS_CHROME_BROWSER_PHYSICAL_WEB_PHYSICAL_WEB_CONSTANTS_H_
diff --git a/ios/chrome/browser/physical_web/physical_web_initial_state_recorder.h b/ios/chrome/browser/physical_web/physical_web_initial_state_recorder.h deleted file mode 100644 index 1d0aabfb..0000000 --- a/ios/chrome/browser/physical_web/physical_web_initial_state_recorder.h +++ /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. - -#ifndef IOS_CHROME_BROWSER_PHYSICAL_WEB_PHYSICAL_WEB_INITIAL_STATE_RECORDER_H_ -#define IOS_CHROME_BROWSER_PHYSICAL_WEB_PHYSICAL_WEB_INITIAL_STATE_RECORDER_H_ - -#import <CoreBluetooth/CoreBluetooth.h> - -class PrefService; - -@interface PhysicalWebInitialStateRecorder : NSObject<CBCentralManagerDelegate> - -- (instancetype)initWithPrefService:(PrefService*)prefService - NS_DESIGNATED_INITIALIZER; - -- (instancetype)init NS_UNAVAILABLE; - -// Fetches and logs the current state of settings relevant to the Physical Web -// feature. -- (void)collectAndRecordState; - -// If the initial state has not yet been recorded, abort collection and -// invalidate the timer. -- (void)invalidate; - -@end - -#endif // IOS_CHROME_BROWSER_PHYSICAL_WEB_PHYSICAL_WEB_INITIAL_STATE_RECORDER_H_
diff --git a/ios/chrome/browser/physical_web/physical_web_initial_state_recorder.mm b/ios/chrome/browser/physical_web/physical_web_initial_state_recorder.mm deleted file mode 100644 index ca76b9d..0000000 --- a/ios/chrome/browser/physical_web/physical_web_initial_state_recorder.mm +++ /dev/null
@@ -1,183 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/physical_web/physical_web_initial_state_recorder.h" - -#import <CoreBluetooth/CoreBluetooth.h> -#import <CoreLocation/CoreLocation.h> - -#include "base/metrics/histogram_macros.h" -#include "components/prefs/pref_service.h" -#include "ios/chrome/browser/physical_web/physical_web_constants.h" -#include "ios/chrome/browser/pref_names.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { - -const double kStartupDelaySeconds = 10.0; - -// Initial state of settings relevant to the Physical Web feature. These are -// ordered so that bits 2:0 encode the Bluetooth enabled state, the Location -// Services enabled state, and whether Chrome has been granted the Location app -// permission. Bits 4:3 encode the Physical Web preference tristate. -// This enum is used in a user metrics histogram. The states should not be -// reordered or removed. -enum PhysicalWebInitialStateIosChrome { - OPTOUT_BTOFF_LOCOFF_UNAUTH, - OPTOUT_BTOFF_LOCOFF_AUTH, - OPTOUT_BTOFF_LOCON_UNAUTH, - OPTOUT_BTOFF_LOCON_AUTH, - OPTOUT_BTON_LOCOFF_UNAUTH, - OPTOUT_BTON_LOCOFF_AUTH, - OPTOUT_BTON_LOCON_UNAUTH, - OPTOUT_BTON_LOCON_AUTH, - OPTIN_BTOFF_LOCOFF_UNAUTH, - OPTIN_BTOFF_LOCOFF_AUTH, - OPTIN_BTOFF_LOCON_UNAUTH, - OPTIN_BTOFF_LOCON_AUTH, - OPTIN_BTON_LOCOFF_UNAUTH, - OPTIN_BTON_LOCOFF_AUTH, - OPTIN_BTON_LOCON_UNAUTH, - OPTIN_BTON_LOCON_AUTH, - ONBOARDING_BTOFF_LOCOFF_UNAUTH, - ONBOARDING_BTOFF_LOCOFF_AUTH, - ONBOARDING_BTOFF_LOCON_UNAUTH, - ONBOARDING_BTOFF_LOCON_AUTH, - ONBOARDING_BTON_LOCOFF_UNAUTH, - ONBOARDING_BTON_LOCOFF_AUTH, - ONBOARDING_BTON_LOCON_UNAUTH, - ONBOARDING_BTON_LOCON_AUTH, - PHYSICAL_WEB_INITIAL_STATE_COUNT, - - // Helper flag values - LOCATION_AUTHORIZED_FLAG = 1 << 0, - LOCATION_SERVICES_FLAG = 1 << 1, - BLUETOOTH_FLAG = 1 << 2, - OPTIN_FLAG = 1 << 3, - ONBOARDING_FLAG = 1 << 4, -}; -} // namespace - -@implementation PhysicalWebInitialStateRecorder { - int preferenceState_; - BOOL recordedState_; - NSTimer* startupDelayTimer_; - CBCentralManager* centralManager_; -} - -- (instancetype)initWithPrefService:(PrefService*)prefService { - self = [super init]; - if (self) { - preferenceState_ = prefService->GetInteger(prefs::kIosPhysicalWebEnabled); - } - return self; -} - -- (instancetype)init { - NOTREACHED(); - return nil; -} - -- (void)dealloc { - [self invalidate]; -} - -- (void)invalidate { - if (startupDelayTimer_) { - [startupDelayTimer_ invalidate]; - startupDelayTimer_ = nil; - } - [centralManager_ setDelegate:nil]; - centralManager_ = nil; -} - -- (void)centralManagerDidUpdateState:(CBCentralManager*)central { - [centralManager_ setDelegate:nil]; - centralManager_ = nil; - - BOOL bluetoothEnabled = NO; - if (@available(iOS 10, *)) { - bluetoothEnabled = [centralManager_ state] == CBManagerStatePoweredOn; - } -#if !defined(__IPHONE_10_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0 - else { - bluetoothEnabled = (CBCentralManagerState)[centralManager_ state] == - CBCentralManagerStatePoweredOn; - } -#endif - - BOOL locationServicesEnabled = [CLLocationManager locationServicesEnabled]; - - CLAuthorizationStatus authStatus = [CLLocationManager authorizationStatus]; - BOOL locationAuthorized = - authStatus == kCLAuthorizationStatusAuthorizedWhenInUse || - authStatus == kCLAuthorizationStatusAuthorizedAlways; - - [self recordStateWithPreferenceState:preferenceState_ - bluetoothEnabled:bluetoothEnabled - locationServicesEnabled:locationServicesEnabled - locationAuthorized:locationAuthorized]; -} - -- (void)collectAndRecordState { - if (recordedState_) { - return; - } - recordedState_ = YES; - startupDelayTimer_ = - [NSTimer scheduledTimerWithTimeInterval:kStartupDelaySeconds - target:self - selector:@selector(startupDelayElapsed:) - userInfo:nil - repeats:NO]; -} - -- (void)startupDelayElapsed:(NSTimer*)timer { - startupDelayTimer_ = nil; - - // The Bluetooth enabled state must be checked asynchronously. When the state - // is ready, it will call our centralManagerDidUpdateState method. - centralManager_ = [[CBCentralManager alloc] - initWithDelegate:self - queue:dispatch_get_main_queue() - options:@{ - // By default, creating a CBCentralManager object with - // Bluetooth disabled will prompt the user to enable Bluetooth. - // Passing ShowPowerAlert=NO disables the prompt so we can - // check the Bluetooth enabled state silently. - CBCentralManagerOptionShowPowerAlertKey : @NO - }]; -} - -- (void)recordStateWithPreferenceState:(int)preferenceState - bluetoothEnabled:(BOOL)bluetoothEnabled - locationServicesEnabled:(BOOL)locationServicesEnabled - locationAuthorized:(BOOL)locationAuthorized { - int state = 0; - if (preferenceState == physical_web::kPhysicalWebOn) { - state |= OPTIN_FLAG; - } else if (preferenceState == physical_web::kPhysicalWebOnboarding) { - state |= ONBOARDING_FLAG; - } - if (locationServicesEnabled) { - state |= LOCATION_SERVICES_FLAG; - } - if (locationAuthorized) { - state |= LOCATION_AUTHORIZED_FLAG; - } - if (bluetoothEnabled) { - state |= BLUETOOTH_FLAG; - } - - DCHECK(state < PHYSICAL_WEB_INITIAL_STATE_COUNT); - UMA_HISTOGRAM_ENUMERATION( - "PhysicalWeb.InitialState.IosChrome", - static_cast<PhysicalWebInitialStateIosChrome>(state), - PHYSICAL_WEB_INITIAL_STATE_COUNT); -} - -@end
diff --git a/ios/chrome/browser/physical_web/physical_web_prefs_registration.cc b/ios/chrome/browser/physical_web/physical_web_prefs_registration.cc deleted file mode 100644 index 7490366..0000000 --- a/ios/chrome/browser/physical_web/physical_web_prefs_registration.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 "ios/chrome/browser/physical_web/physical_web_prefs_registration.h" - -#include "components/pref_registry/pref_registry_syncable.h" -#include "components/prefs/pref_registry_simple.h" -#include "ios/chrome/browser/physical_web/physical_web_constants.h" -#include "ios/chrome/browser/pref_names.h" - -void RegisterPhysicalWebBrowserStatePrefs( - user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterIntegerPref( - prefs::kIosPhysicalWebEnabled, physical_web::kPhysicalWebOnboarding, - user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); -} - -void RegisterPhysicalWebLocalStatePrefs(PrefRegistrySimple* registry) { - registry->RegisterIntegerPref(prefs::kIosPhysicalWebEnabled, - physical_web::kPhysicalWebOnboarding); -}
diff --git a/ios/chrome/browser/physical_web/physical_web_prefs_registration.h b/ios/chrome/browser/physical_web/physical_web_prefs_registration.h deleted file mode 100644 index bccfa9c..0000000 --- a/ios/chrome/browser/physical_web/physical_web_prefs_registration.h +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_PHYSICAL_WEB_PHYSICAL_WEB_PREFS_REGISTRATION_H_ -#define IOS_CHROME_BROWSER_PHYSICAL_WEB_PHYSICAL_WEB_PREFS_REGISTRATION_H_ - -class PrefRegistrySimple; -namespace user_prefs { -class PrefRegistrySyncable; -} - -// Registers browser state prefs needed by the Physical Web. -void RegisterPhysicalWebBrowserStatePrefs( - user_prefs::PrefRegistrySyncable* registry); - -// Registers local state prefs needed by the Physical Web. -void RegisterPhysicalWebLocalStatePrefs(PrefRegistrySimple* registry); - -#endif // IOS_CHROME_BROWSER_PHYSICAL_WEB_PHYSICAL_WEB_PREFS_REGISTRATION_H_
diff --git a/ios/chrome/browser/physical_web/start_physical_web_discovery.h b/ios/chrome/browser/physical_web/start_physical_web_discovery.h deleted file mode 100644 index 65e4981d..0000000 --- a/ios/chrome/browser/physical_web/start_physical_web_discovery.h +++ /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. - -#ifndef IOS_CHROME_BROWSER_PHYSICAL_WEB_START_PHYSICAL_WEB_DISCOVERY_H_ -#define IOS_CHROME_BROWSER_PHYSICAL_WEB_START_PHYSICAL_WEB_DISCOVERY_H_ - -#include "components/prefs/pref_service.h" - -namespace ios { -class ChromeBrowserState; -} - -// Checks the environment and starts Physical Web discovery if the required -// conditions are met. -void StartPhysicalWebDiscovery(PrefService* pref_service, - ios::ChromeBrowserState* browser_state); - -#endif // IOS_CHROME_BROWSER_PHYSICAL_WEB_START_PHYSICAL_WEB_DISCOVERY_H_
diff --git a/ios/chrome/browser/physical_web/start_physical_web_discovery.mm b/ios/chrome/browser/physical_web/start_physical_web_discovery.mm deleted file mode 100644 index 0a0734c15..0000000 --- a/ios/chrome/browser/physical_web/start_physical_web_discovery.mm +++ /dev/null
@@ -1,81 +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 "ios/chrome/browser/physical_web/start_physical_web_discovery.h" - -#import <CoreLocation/CoreLocation.h> - -#include "components/physical_web/data_source/physical_web_data_source.h" -#include "components/search_engines/search_terms_data.h" -#include "components/search_engines/template_url_service.h" -#include "ios/chrome/browser/application_context.h" -#include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#import "ios/chrome/browser/experimental_flags.h" -#import "ios/chrome/browser/geolocation/omnibox_geolocation_config.h" -#include "ios/chrome/browser/physical_web/physical_web_constants.h" -#include "ios/chrome/browser/pref_names.h" -#include "ios/chrome/browser/search_engines/template_url_service_factory.h" -#include "url/gurl.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -void StartPhysicalWebDiscovery(PrefService* pref_service, - ios::ChromeBrowserState* browser_state) { - // Do not scan if the Physical Web feature is disabled by a command line flag - // or Chrome Variations experiment. - if (!experimental_flags::IsPhysicalWebEnabled()) { - return; - } - - // If the preference is in the default state, check if conditions allow us to - // auto-enable it. The preference can be auto-enabled if the omnibox would - // send the X-Geo geolocation header in search queries to www.google.com. - int preference_state = - pref_service->GetInteger(prefs::kIosPhysicalWebEnabled); - if (preference_state == physical_web::kPhysicalWebOnboarding) { - // Check whether the user is in Incognito mode. Physical Web will only be - // auto-enabled if the user is not in Incognito. - bool is_incognito = browser_state->IsOffTheRecord(); - - // Check that Location Services is enabled. - bool location_services_enabled = - [CLLocationManager locationServicesEnabled]; - - // Check that the user has authorized Chrome to use location. - CLAuthorizationStatus auth_status = [CLLocationManager authorizationStatus]; - bool location_authorized = - auth_status == kCLAuthorizationStatusAuthorizedWhenInUse || - auth_status == kCLAuthorizationStatusAuthorizedAlways; - - // Check that the user has not revoked the geolocation permission for - // Google. - bool geolocation_eligible = [[OmniboxGeolocationConfig sharedInstance] - URLHasEligibleDomain:GURL("https://www.google.com")]; - - // Check that Google Search is configured as the default search engine. - const TemplateURL* default_search_provider = - ios::TemplateURLServiceFactory::GetForBrowserState(browser_state) - ->GetDefaultSearchProvider(); - bool google_search_enabled = - default_search_provider->IsGoogleSearchURLWithReplaceableKeyword( - SearchTermsData()); - - if (!is_incognito && location_services_enabled && location_authorized && - geolocation_eligible && google_search_enabled) { - pref_service->SetInteger(prefs::kIosPhysicalWebEnabled, - physical_web::kPhysicalWebOn); - } - preference_state = pref_service->GetInteger(prefs::kIosPhysicalWebEnabled); - } - - // Scan only if the feature is enabled. - if (preference_state == physical_web::kPhysicalWebOn) { - GetApplicationContext()->GetPhysicalWebDataSource()->StartDiscovery(true); - } else { - GetApplicationContext()->GetPhysicalWebDataSource()->StopDiscovery(); - } -} -
diff --git a/ios/chrome/browser/pref_names.cc b/ios/chrome/browser/pref_names.cc index 99251740..5bdf9f6 100644 --- a/ios/chrome/browser/pref_names.cc +++ b/ios/chrome/browser/pref_names.cc
@@ -81,10 +81,6 @@ const char kIosSettingsSigninPromoDisplayedCount[] = "ios.settings.signin_promo_displayed_count"; -// Whether the user has enabled the Physical Web feature to surface URLs -// broadcast by nearby devices. -const char kIosPhysicalWebEnabled[] = "ios.physical_web_enabled"; - // True if the previous session exited cleanly. // This can be different from kStabilityExitedCleanly, because the last run of // the program may not have included a browsing session, and thus the last run
diff --git a/ios/chrome/browser/pref_names.h b/ios/chrome/browser/pref_names.h index 105e4a3..5a0c3cd 100644 --- a/ios/chrome/browser/pref_names.h +++ b/ios/chrome/browser/pref_names.h
@@ -26,7 +26,6 @@ extern const char kIosBookmarkSigninPromoDisplayedCount[]; extern const char kIosSettingsPromoAlreadySeen[]; extern const char kIosSettingsSigninPromoDisplayedCount[]; -extern const char kIosPhysicalWebEnabled[]; extern const char kLastSessionExitedCleanly[]; extern const char kMetricsReportingWifiOnly[]; extern const char kNtpShownPage[];
diff --git a/ios/chrome/browser/prefs/BUILD.gn b/ios/chrome/browser/prefs/BUILD.gn index 3f80d2f..ae27eef 100644 --- a/ios/chrome/browser/prefs/BUILD.gn +++ b/ios/chrome/browser/prefs/BUILD.gn
@@ -67,7 +67,6 @@ "//ios/chrome/browser/memory", "//ios/chrome/browser/metrics", "//ios/chrome/browser/net", - "//ios/chrome/browser/physical_web", "//ios/chrome/browser/signin", "//ios/chrome/browser/ui/authentication", "//ios/chrome/browser/ui/bookmarks",
diff --git a/ios/chrome/browser/prefs/browser_prefs.mm b/ios/chrome/browser/prefs/browser_prefs.mm index d3d6f2e8..be4f23cc 100644 --- a/ios/chrome/browser/prefs/browser_prefs.mm +++ b/ios/chrome/browser/prefs/browser_prefs.mm
@@ -45,7 +45,6 @@ #import "ios/chrome/browser/memory/memory_debugger_manager.h" #import "ios/chrome/browser/metrics/ios_chrome_metrics_service_client.h" #include "ios/chrome/browser/notification_promo.h" -#include "ios/chrome/browser/physical_web/physical_web_prefs_registration.h" #include "ios/chrome/browser/pref_names.h" #include "ios/chrome/browser/signin/signin_manager_factory.h" #import "ios/chrome/browser/ui/authentication/signin_promo_view_mediator.h" @@ -71,7 +70,6 @@ ssl_config::SSLConfigServiceManager::RegisterPrefs(registry); update_client::RegisterPrefs(registry); variations::VariationsService::RegisterPrefs(registry); - RegisterPhysicalWebLocalStatePrefs(registry); // Preferences related to the browser state manager. registry->RegisterStringPref(prefs::kBrowserStateLastUsed, std::string());
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index 8023ab5..7ef1020 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -5083,9 +5083,21 @@ _infoBarContainer->ChangeInfoBarManager(infoBarManager); } - // Add |newTab|'s view to the hierarchy if it's the current Tab. - if (self.active && model.currentTab == newTab) + if (self.active && model.currentTab == newTab) { + // Add |newTab|'s view to the hierarchy if it's the current Tab. [self displayTab:newTab isNewSelection:NO]; + // Reset the temporary native controller since the current tab is replaced. + _temporaryNativeController = nil; + // If this is occurring for an inserted prerender tab, update its content + // offset so that it's below the toolbar. + if (_insertedTabWasPrerenderedTab) { + CRWWebViewProxyType webViewProxy = newTab.webState->GetWebViewProxy(); + CRWWebViewScrollViewProxy* scrollProxy = webViewProxy.scrollViewProxy; + CGFloat toolbarHeight = [self toolbarHeight]; + scrollProxy.contentOffset = CGPointMake(0, -toolbarHeight); + webViewProxy.topContentPadding = toolbarHeight; + } + } if (newTab) [_paymentRequestManager setActiveWebState:newTab.webState];
diff --git a/ios/chrome/browser/ui/fullscreen/BUILD.gn b/ios/chrome/browser/ui/fullscreen/BUILD.gn index 820772ff..c9bb9fc 100644 --- a/ios/chrome/browser/ui/fullscreen/BUILD.gn +++ b/ios/chrome/browser/ui/fullscreen/BUILD.gn
@@ -41,8 +41,9 @@ source_set("new_fullscreen_internal") { sources = [ - "fullscreen_controller.mm", "fullscreen_controller_factory.mm", + "fullscreen_controller_impl.h", + "fullscreen_controller_impl.mm", "fullscreen_mediator.h", "fullscreen_mediator.mm", "fullscreen_model.h", @@ -53,8 +54,8 @@ "fullscreen_web_state_list_observer.mm", "fullscreen_web_state_observer.h", "fullscreen_web_state_observer.mm", - "voice_over_fullscreen_disabler.h", - "voice_over_fullscreen_disabler.mm", + "system_notification_fullscreen_disabler.h", + "system_notification_fullscreen_disabler.mm", ] configs += [ "//build/config/compiler:enable_arc" ]
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_controller.h b/ios/chrome/browser/ui/fullscreen/fullscreen_controller.h index 2ea797d1..88ce436 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_controller.h +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_controller.h
@@ -2,22 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CLEAN_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_H_ -#define IOS_CLEAN_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_H_ +#ifndef IOS_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_H_ #import <Foundation/Foundation.h> -#include <memory> #include "base/macros.h" #include "components/keyed_service/core/keyed_service.h" @class ChromeBroadcaster; -@class ChromeBroadcastOberverBridge; class FullscreenControllerObserver; -class FullscreenMediator; -class FullscreenModel; -class FullscreenWebStateListObserver; -@class VoiceOverFullscreenDisabler; class WebStateList; // An object that observes scrolling events in the main content area and @@ -26,26 +20,25 @@ // the page's content to be visible. class FullscreenController : public KeyedService { public: - explicit FullscreenController(); - ~FullscreenController() override; + explicit FullscreenController() = default; // The ChromeBroadcaster through the FullscreenController receives UI // information necessary to calculate fullscreen progress. // TODO(crbug.com/790886): Once FullscreenController is a BrowserUserData, // remove this ad-hoc broadcaster and drive the animations via the Browser's // ChromeBroadcaster. - ChromeBroadcaster* broadcaster() { return broadcaster_; } + virtual ChromeBroadcaster* broadcaster() = 0; // The WebStateList for the Browser whose fullscreen state is managed by this // controller. // TODO(crbug.com/790886): Once FullscreenController is a BrowserUserData, // remove this, as the Browser's WebStateList can be used directly rather than // being set. - void SetWebStateList(WebStateList* web_state_list); + virtual void SetWebStateList(WebStateList* web_state_list) = 0; // Adds and removes FullscreenControllerObservers. - void AddObserver(FullscreenControllerObserver* observer); - void RemoveObserver(FullscreenControllerObserver* observer); + virtual void AddObserver(FullscreenControllerObserver* observer) = 0; + virtual void RemoveObserver(FullscreenControllerObserver* observer) = 0; // FullscreenController can be disabled when a feature requires that the // toolbar be fully visible. Since there are multiple reasons fullscreen @@ -55,31 +48,13 @@ // the toolbar, it calls DecrementDisabledCounter(). IsEnabled() returns // true when the counter is equal to zero. ScopedFullscreenDisabler can be // used to tie a disabled counter to an object's lifetime. - bool IsEnabled() const; - void IncrementDisabledCounter(); - void DecrementDisabledCounter(); + virtual bool IsEnabled() const = 0; + virtual void IncrementDisabledCounter() = 0; + virtual void DecrementDisabledCounter() = 0; private: - // KeyedService: - void Shutdown() override; - - // The broadcaster that drives the model. - __strong ChromeBroadcaster* broadcaster_ = nil; - // The WebStateList for the Browser whose fullscreen is managed by this - // object. - WebStateList* web_state_list_ = nullptr; - // The model used to calculate fullscreen state. - std::unique_ptr<FullscreenModel> model_; - // The bridge used to forward brodcasted UI to |model_|. - __strong ChromeBroadcastOberverBridge* bridge_ = nil; - // A helper object that disables fullscreen when VoiceOver is enabled. - __strong VoiceOverFullscreenDisabler* voice_over_disabler_ = nil; - // Object that manages sending signals to FullscreenControllerObservers. - std::unique_ptr<FullscreenMediator> mediator_; - // A WebStateListObserver that updates |model_| for WebStateList changes. - std::unique_ptr<FullscreenWebStateListObserver> web_state_list_observer_; DISALLOW_COPY_AND_ASSIGN(FullscreenController); }; -#endif // IOS_CLEAN_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_H_ +#endif // IOS_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_controller_factory.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_controller_factory.mm index f16bdf0..750d293e 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_controller_factory.mm +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_controller_factory.mm
@@ -11,7 +11,7 @@ #include "components/keyed_service/ios/browser_state_dependency_manager.h" #include "ios/chrome/browser/browser_state/browser_state_otr_helper.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller.h" +#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -37,7 +37,7 @@ std::unique_ptr<KeyedService> FullscreenControllerFactory::BuildServiceInstanceFor( web::BrowserState* context) const { - return base::MakeUnique<FullscreenController>(); + return base::MakeUnique<FullscreenControllerImpl>(); } web::BrowserState* FullscreenControllerFactory::GetBrowserStateToUse(
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.h b/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.h new file mode 100644 index 0000000..a29650d --- /dev/null +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.h
@@ -0,0 +1,56 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_IMPL_H_ +#define IOS_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_IMPL_H_ + +#include <memory> + +#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller.h" + +@class ChromeBroadcastOberverBridge; +class FullscreenMediator; +class FullscreenModel; +class FullscreenWebStateListObserver; +@class SystemNotificationFullscreenDisabler; + +// Implementation of FullscreenController. +class FullscreenControllerImpl : public FullscreenController { + public: + explicit FullscreenControllerImpl(); + ~FullscreenControllerImpl() override; + + // FullscreenController: + ChromeBroadcaster* broadcaster() override; + void SetWebStateList(WebStateList* web_state_list) override; + void AddObserver(FullscreenControllerObserver* observer) override; + void RemoveObserver(FullscreenControllerObserver* observer) override; + bool IsEnabled() const override; + void IncrementDisabledCounter() override; + void DecrementDisabledCounter() override; + + private: + // KeyedService: + void Shutdown() override; + + // The broadcaster that drives the model. + __strong ChromeBroadcaster* broadcaster_ = nil; + // The WebStateList for the Browser whose fullscreen is managed by this + // object. + WebStateList* web_state_list_ = nullptr; + // The model used to calculate fullscreen state. + std::unique_ptr<FullscreenModel> model_; + // The bridge used to forward brodcasted UI to |model_|. + __strong ChromeBroadcastOberverBridge* bridge_ = nil; + // A helper object that disables fullscreen for system notifications. + __strong SystemNotificationFullscreenDisabler* disabler_ = nil; + // Object that manages sending signals to FullscreenControllerImplObservers. + std::unique_ptr<FullscreenMediator> mediator_; + // A WebStateListObserver that updates |model_| for WebStateList changes. + std::unique_ptr<FullscreenWebStateListObserver> web_state_list_observer_; + + DISALLOW_COPY_AND_ASSIGN(FullscreenControllerImpl); +}; + +#endif // IOS_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_IMPL_H_
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_controller.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.mm similarity index 68% rename from ios/chrome/browser/ui/fullscreen/fullscreen_controller.mm rename to ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.mm index 6633595f..8bc38a9 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_controller.mm +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller.h" +#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.h" #include "base/memory/ptr_util.h" #import "ios/chrome/browser/ui/broadcaster/chrome_broadcast_observer_bridge.h" @@ -10,19 +10,20 @@ #import "ios/chrome/browser/ui/fullscreen/fullscreen_mediator.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_model.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_web_state_list_observer.h" -#import "ios/chrome/browser/ui/fullscreen/voice_over_fullscreen_disabler.h" +#import "ios/chrome/browser/ui/fullscreen/system_notification_fullscreen_disabler.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif -FullscreenController::FullscreenController() - : broadcaster_([[ChromeBroadcaster alloc] init]), +FullscreenControllerImpl::FullscreenControllerImpl() + : FullscreenController(), + broadcaster_([[ChromeBroadcaster alloc] init]), model_(base::MakeUnique<FullscreenModel>()), bridge_( [[ChromeBroadcastOberverBridge alloc] initWithObserver:model_.get()]), - voice_over_disabler_( - [[VoiceOverFullscreenDisabler alloc] initWithController:this]), + disabler_([[SystemNotificationFullscreenDisabler alloc] + initWithController:this]), mediator_(base::MakeUnique<FullscreenMediator>(this, model_.get())) { DCHECK(broadcaster_); [broadcaster_ addObserver:bridge_ @@ -35,42 +36,47 @@ forSelector:@selector(broadcastToolbarHeight:)]; } -FullscreenController::~FullscreenController() = default; +FullscreenControllerImpl::~FullscreenControllerImpl() = default; -void FullscreenController::SetWebStateList(WebStateList* web_state_list) { +ChromeBroadcaster* FullscreenControllerImpl::broadcaster() { + return broadcaster_; +} + +void FullscreenControllerImpl::SetWebStateList(WebStateList* web_state_list) { if (web_state_list_observer_) web_state_list_observer_->Disconnect(); web_state_list_ = web_state_list; web_state_list_observer_ = web_state_list_ ? base::MakeUnique<FullscreenWebStateListObserver>( - model_.get(), web_state_list_) + this, model_.get(), web_state_list_) : nullptr; } -void FullscreenController::AddObserver(FullscreenControllerObserver* observer) { +void FullscreenControllerImpl::AddObserver( + FullscreenControllerObserver* observer) { mediator_->AddObserver(observer); } -void FullscreenController::RemoveObserver( +void FullscreenControllerImpl::RemoveObserver( FullscreenControllerObserver* observer) { mediator_->RemoveObserver(observer); } -bool FullscreenController::IsEnabled() const { +bool FullscreenControllerImpl::IsEnabled() const { return model_->enabled(); } -void FullscreenController::IncrementDisabledCounter() { +void FullscreenControllerImpl::IncrementDisabledCounter() { model_->IncrementDisabledCounter(); } -void FullscreenController::DecrementDisabledCounter() { +void FullscreenControllerImpl::DecrementDisabledCounter() { model_->DecrementDisabledCounter(); } -void FullscreenController::Shutdown() { +void FullscreenControllerImpl::Shutdown() { mediator_->Disconnect(); - [voice_over_disabler_ disconnect]; + [disabler_ disconnect]; if (web_state_list_observer_) web_state_list_observer_->Disconnect(); [broadcaster_ removeObserver:bridge_
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_list_observer.h b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_list_observer.h index ded213e..8564e18 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_list_observer.h +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_list_observer.h
@@ -9,6 +9,7 @@ #import "ios/chrome/browser/web_state_list/web_state_list_observer.h" #include "ios/web/public/web_state/web_state_observer.h" +class FullscreenController; class FullscreenModel; // A WebStateListObserver that creates WebStateObservers that update a @@ -16,7 +17,10 @@ class FullscreenWebStateListObserver : public WebStateListObserver { public: // Constructor for an observer for |web_state_list| that updates |model|. - FullscreenWebStateListObserver(FullscreenModel* model, + // |controller| is used to create ScopedFullscreenDisablers for WebState + // navigation events that require the toolbar to be visible. + FullscreenWebStateListObserver(FullscreenController* controller, + FullscreenModel* model, WebStateList* web_state_list); ~FullscreenWebStateListObserver() override; @@ -25,6 +29,10 @@ private: // WebStateListObserver: + void WebStateReplacedAt(WebStateList* web_state_list, + web::WebState* old_web_state, + web::WebState* new_web_state, + int index) override; void WebStateActivatedAt(WebStateList* web_state_list, web::WebState* old_web_state, web::WebState* new_web_state,
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_list_observer.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_list_observer.mm index 94207252..95f1820 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_list_observer.mm +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_list_observer.mm
@@ -5,6 +5,7 @@ #import "ios/chrome/browser/ui/fullscreen/fullscreen_web_state_list_observer.h" #include "base/logging.h" +#import "ios/chrome/browser/ui/fullscreen/fullscreen_model.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -12,11 +13,12 @@ #endif FullscreenWebStateListObserver::FullscreenWebStateListObserver( + FullscreenController* controller, FullscreenModel* model, WebStateList* web_state_list) : model_(model), web_state_list_(web_state_list), - web_state_observer_(model) { + web_state_observer_(controller, model) { DCHECK(model_); DCHECK(web_state_list_); web_state_list_->AddObserver(this); @@ -34,6 +36,18 @@ web_state_observer_.SetWebState(nullptr); } +void FullscreenWebStateListObserver::WebStateReplacedAt( + WebStateList* web_state_list, + web::WebState* old_web_state, + web::WebState* new_web_state, + int index) { + if (new_web_state == web_state_list->GetActiveWebState()) { + // Reset the model if the active WebState is replaced. + web_state_observer_.SetWebState(new_web_state); + model_->ResetForNavigation(); + } +} + void FullscreenWebStateListObserver::WebStateActivatedAt( WebStateList* web_state_list, web::WebState* old_web_state,
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_list_observer_unittest.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_list_observer_unittest.mm index 134e694..1333401 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_list_observer_unittest.mm +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_list_observer_unittest.mm
@@ -7,6 +7,7 @@ #include "base/memory/ptr_util.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_model.h" #import "ios/chrome/browser/ui/fullscreen/test/fullscreen_model_test_util.h" +#import "ios/chrome/browser/ui/fullscreen/test/test_fullscreen_controller.h" #import "ios/chrome/browser/web_state_list/fake_web_state_list_delegate.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/chrome/browser/web_state_list/web_state_opener.h" @@ -25,8 +26,9 @@ public: FullscreenWebStateListObserverTest() : PlatformTest(), + controller_(&model_), web_state_list_(&web_state_list_delegate_), - observer_(&model_, &web_state_list_) { + observer_(&controller_, &model_, &web_state_list_) { SetUpFullscreenModelForTesting(&model_, 100.0); } @@ -40,6 +42,7 @@ private: FullscreenModel model_; + TestFullscreenController controller_; FakeWebStateListDelegate web_state_list_delegate_; WebStateList web_state_list_; FullscreenWebStateListObserver observer_;
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.h b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.h index 9bf5d54..78a6fcb 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.h +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.h
@@ -5,15 +5,21 @@ #ifndef IOS_CLEAN_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_WEB_STATE_OBSERVER_H_ #define IOS_CLEAN_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_WEB_STATE_OBSERVER_H_ +#include <memory> + #include "ios/web/public/web_state/web_state_observer.h" +class FullscreenController; class FullscreenModel; +class ScopedFullscreenDisabler; // A WebStateObserver that updates a FullscreenModel for navigation events. class FullscreenWebStateObserver : public web::WebStateObserver { public: - // Constructor for an observer that updates |model|. - FullscreenWebStateObserver(FullscreenModel* model); + // Constructor for an observer that updates |controller| and |model|. + FullscreenWebStateObserver(FullscreenController* controller, + FullscreenModel* model); + ~FullscreenWebStateObserver() override; // Tells the observer to start observing |web_state|. void SetWebState(web::WebState* web_state); @@ -25,6 +31,7 @@ void DidStartLoading(web::WebState* web_state) override; void DidStopLoading(web::WebState* web_state) override; void DidChangeVisibleSecurityState(web::WebState* web_state) override; + void WebStateDestroyed(web::WebState* web_state) override; // Setter for whether the current page's SSL is broken. void SetIsSSLBroken(bool broken); // Setter for whether the WebState is currently loading. @@ -32,12 +39,14 @@ // The WebState being observed. web::WebState* web_state_ = nullptr; + // The FullscreenController passed on construction. + FullscreenController* controller_; // The model passed on construction. FullscreenModel* model_; - // Whether the page's SSL is broken. - bool ssl_broken_ = false; - // Whether the WebState is loading. - bool loading_ = false; + // The disabler for broken SSL. + std::unique_ptr<ScopedFullscreenDisabler> ssl_disabler_; + // The disabler for loading. + std::unique_ptr<ScopedFullscreenDisabler> loading_disabler_; }; #endif // IOS_CLEAN_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_WEB_STATE_OBSERVER_H_
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.mm index 69065285..0220ed3 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.mm +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.mm
@@ -5,7 +5,9 @@ #import "ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_model.h" +#import "ios/chrome/browser/ui/fullscreen/scoped_fullscreen_disabler.h" #import "ios/web/public/navigation_item.h" #import "ios/web/public/navigation_manager.h" #include "ios/web/public/ssl_status.h" @@ -31,11 +33,16 @@ } } // namespace -FullscreenWebStateObserver::FullscreenWebStateObserver(FullscreenModel* model) - : model_(model) { +FullscreenWebStateObserver::FullscreenWebStateObserver( + FullscreenController* controller, + FullscreenModel* model) + : controller_(controller), model_(model) { + DCHECK(controller_); DCHECK(model_); } +FullscreenWebStateObserver::~FullscreenWebStateObserver() = default; + void FullscreenWebStateObserver::SetWebState(web::WebState* web_state) { if (web_state_ == web_state) return; @@ -68,24 +75,23 @@ SetIsSSLBroken(IsWebStateSSLBroken(web_state)); } +void FullscreenWebStateObserver::WebStateDestroyed(web::WebState* web_state) { + DCHECK_EQ(web_state, web_state_); + SetWebState(nullptr); +} + void FullscreenWebStateObserver::SetIsSSLBroken(bool broken) { - if (ssl_broken_ == broken) + if (!!ssl_disabler_.get() == broken) return; - ssl_broken_ = broken; - // Fullscreen should be disbaled for pages with broken SSL. - if (ssl_broken_) - model_->IncrementDisabledCounter(); - else - model_->DecrementDisabledCounter(); + ssl_disabler_ = broken + ? base::MakeUnique<ScopedFullscreenDisabler>(controller_) + : nullptr; } void FullscreenWebStateObserver::SetIsLoading(bool loading) { - if (loading_ == loading) + if (!!loading_disabler_.get() == loading) return; - loading_ = loading; - // Fullscreen should be disabled while the web view is loading. - if (loading_) - model_->IncrementDisabledCounter(); - else - model_->DecrementDisabledCounter(); + loading_disabler_ = + loading ? base::MakeUnique<ScopedFullscreenDisabler>(controller_) + : nullptr; }
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer_unittest.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer_unittest.mm index 08abf24..11224712 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer_unittest.mm +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_web_state_observer_unittest.mm
@@ -7,6 +7,7 @@ #include "base/memory/ptr_util.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_model.h" #import "ios/chrome/browser/ui/fullscreen/test/fullscreen_model_test_util.h" +#import "ios/chrome/browser/ui/fullscreen/test/test_fullscreen_controller.h" #import "ios/web/public/navigation_item.h" #include "ios/web/public/ssl_status.h" #import "ios/web/public/test/fakes/fake_navigation_context.h" @@ -20,7 +21,8 @@ class FullscreenWebStateObserverTest : public PlatformTest { public: - FullscreenWebStateObserverTest() : PlatformTest(), observer_(&model_) { + FullscreenWebStateObserverTest() + : PlatformTest(), controller_(&model_), observer_(&controller_, &model_) { // Set up model. SetUpFullscreenModelForTesting(&model_, 100.0); // Set up a TestNavigationManager. @@ -45,6 +47,7 @@ private: FullscreenModel model_; + TestFullscreenController controller_; web::TestWebState web_state_; web::TestNavigationManager* navigation_manager_; FullscreenWebStateObserver observer_;
diff --git a/ios/chrome/browser/ui/fullscreen/system_notification_fullscreen_disabler.h b/ios/chrome/browser/ui/fullscreen/system_notification_fullscreen_disabler.h new file mode 100644 index 0000000..a7bcd3b --- /dev/null +++ b/ios/chrome/browser/ui/fullscreen/system_notification_fullscreen_disabler.h
@@ -0,0 +1,28 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_FULLSCREEN_SYSTEM_NOTIFICATION_FULLSCREEN_DISABLER_H_ +#define IOS_CHROME_BROWSER_UI_FULLSCREEN_SYSTEM_NOTIFICATION_FULLSCREEN_DISABLER_H_ + +#import <UIKit/UIKit.h> + +class FullscreenController; + +// Helper class that handles disabling fullscreen due to NSNotifications sent +// by system frameworks. This class disables fullscreen: +// - when VoiceOver is enabled, +// - when the software keyboard is visible. +@interface SystemNotificationFullscreenDisabler : NSObject + +// Designated initializer that disables |controller| for system notifications. +- (nullable instancetype)initWithController: + (nonnull FullscreenController*)controller NS_DESIGNATED_INITIALIZER; +- (nullable instancetype)init NS_UNAVAILABLE; + +// Stops observing VoiceOver notifications. +- (void)disconnect; + +@end + +#endif // IOS_CHROME_BROWSER_UI_FULLSCREEN_SYSTEM_NOTIFICATION_FULLSCREEN_DISABLER_H_
diff --git a/ios/chrome/browser/ui/fullscreen/system_notification_fullscreen_disabler.mm b/ios/chrome/browser/ui/fullscreen/system_notification_fullscreen_disabler.mm new file mode 100644 index 0000000..ebbd2621a --- /dev/null +++ b/ios/chrome/browser/ui/fullscreen/system_notification_fullscreen_disabler.mm
@@ -0,0 +1,104 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/fullscreen/system_notification_fullscreen_disabler.h" + +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller.h" +#import "ios/chrome/browser/ui/fullscreen/scoped_fullscreen_disabler.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface SystemNotificationFullscreenDisabler () { + // The disabler created when VoiceOver is enabled. + std::unique_ptr<ScopedFullscreenDisabler> _voiceOverDisabler; + // The disabler created when the keyboard is visible. + std::unique_ptr<ScopedFullscreenDisabler> _keyboardDisabler; +} +// The FullscreenController being enabled/disabled for VoiceOver. +@property(nonatomic, readonly, nonnull) FullscreenController* controller; +// Creates or destroys |_voiceOverDisabler| depending on whether VoiceOver is +// enabled. +- (void)voiceOverStatusChanged; +// Called when the keyboard is shown/hidden to reset |_keyboardDisabler|. +- (void)keyboardWillShow; +- (void)keyboardDidHide; +@end + +@implementation SystemNotificationFullscreenDisabler +@synthesize controller = _controller; + +- (instancetype)initWithController:(FullscreenController*)controller { + if (self = [super init]) { + _controller = controller; + DCHECK(_controller); + // Register for VoiceOVer status change notifications. The notification + // name has been updated in iOS 11. + if (@available(iOS 11, *)) { + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(voiceOverStatusChanged) + name:UIAccessibilityVoiceOverStatusDidChangeNotification + object:nil]; + } else { + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(voiceOverStatusChanged) + name:UIAccessibilityVoiceOverStatusChanged + object:nil]; + } + // Create a disabler if VoiceOver is enabled. + if (UIAccessibilityIsVoiceOverRunning()) { + _voiceOverDisabler = + base::MakeUnique<ScopedFullscreenDisabler>(_controller); + } + // Regsiter for keyboard visibility notifications. + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(keyboardWillShow) + name:UIKeyboardWillShowNotification + object:nil]; + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(keyboardDidHide) + name:UIKeyboardDidHideNotification + object:nil]; + } + return self; +} + +- (void)dealloc { + // |-disconnect| should be called before deallocation. + DCHECK(!_controller); +} + +#pragma mark Public + +- (void)disconnect { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + _controller = nullptr; +} + +#pragma mark Private + +- (void)voiceOverStatusChanged { + _voiceOverDisabler = + UIAccessibilityIsVoiceOverRunning() + ? base::MakeUnique<ScopedFullscreenDisabler>(self.controller) + : nullptr; +} + +- (void)keyboardWillShow { + _keyboardDisabler = + base::MakeUnique<ScopedFullscreenDisabler>(self.controller); +} + +- (void)keyboardDidHide { + _keyboardDisabler = nullptr; +} + +@end
diff --git a/ios/chrome/browser/ui/fullscreen/test/BUILD.gn b/ios/chrome/browser/ui/fullscreen/test/BUILD.gn index 6907599..7c40ad5b 100644 --- a/ios/chrome/browser/ui/fullscreen/test/BUILD.gn +++ b/ios/chrome/browser/ui/fullscreen/test/BUILD.gn
@@ -7,6 +7,8 @@ sources = [ "fullscreen_model_test_util.h", "fullscreen_model_test_util.mm", + "test_fullscreen_controller.h", + "test_fullscreen_controller.mm", "test_fullscreen_controller_observer.h", "test_fullscreen_controller_observer.mm", "test_fullscreen_model_observer.h",
diff --git a/ios/chrome/browser/ui/fullscreen/test/test_fullscreen_controller.h b/ios/chrome/browser/ui/fullscreen/test/test_fullscreen_controller.h new file mode 100644 index 0000000..934d01d --- /dev/null +++ b/ios/chrome/browser/ui/fullscreen/test/test_fullscreen_controller.h
@@ -0,0 +1,33 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_FULLSCREEN_TEST_TEST_FULLSCREEN_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_FULLSCREEN_TEST_TEST_FULLSCREEN_CONTROLLER_H_ + +#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller.h" + +class FullscreenModel; + +// Test version of FullscreenController that enables and disabled the +// FullscreenModel passed on initialization. +class TestFullscreenController : public FullscreenController { + public: + explicit TestFullscreenController(FullscreenModel* model); + ~TestFullscreenController() override; + + // FullscreenController: + ChromeBroadcaster* broadcaster() override; + void SetWebStateList(WebStateList* web_state_list) override; + void AddObserver(FullscreenControllerObserver* observer) override; + void RemoveObserver(FullscreenControllerObserver* observer) override; + bool IsEnabled() const override; + void IncrementDisabledCounter() override; + void DecrementDisabledCounter() override; + + private: + // The model. + FullscreenModel* model_; +}; + +#endif // IOS_CHROME_BROWSER_UI_FULLSCREEN_TEST_TEST_FULLSCREEN_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/fullscreen/test/test_fullscreen_controller.mm b/ios/chrome/browser/ui/fullscreen/test/test_fullscreen_controller.mm new file mode 100644 index 0000000..88228f9 --- /dev/null +++ b/ios/chrome/browser/ui/fullscreen/test/test_fullscreen_controller.mm
@@ -0,0 +1,40 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/fullscreen/test/test_fullscreen_controller.h" + +#import "ios/chrome/browser/ui/fullscreen/fullscreen_model.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +TestFullscreenController::TestFullscreenController(FullscreenModel* model) + : FullscreenController(), model_(model) {} + +TestFullscreenController::~TestFullscreenController() = default; + +ChromeBroadcaster* TestFullscreenController::broadcaster() { + return nil; +} + +void TestFullscreenController::SetWebStateList(WebStateList* web_state_list) {} + +void TestFullscreenController::AddObserver( + FullscreenControllerObserver* observer) {} + +void TestFullscreenController::RemoveObserver( + FullscreenControllerObserver* observer) {} + +bool TestFullscreenController::IsEnabled() const { + return model_->enabled(); +} + +void TestFullscreenController::IncrementDisabledCounter() { + model_->IncrementDisabledCounter(); +} + +void TestFullscreenController::DecrementDisabledCounter() { + model_->DecrementDisabledCounter(); +}
diff --git a/ios/chrome/browser/ui/fullscreen/voice_over_fullscreen_disabler.h b/ios/chrome/browser/ui/fullscreen/voice_over_fullscreen_disabler.h deleted file mode 100644 index df77e9e..0000000 --- a/ios/chrome/browser/ui/fullscreen/voice_over_fullscreen_disabler.h +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_FULLSCREEN_VOICE_OVER_FULLSCREEN_DISABLER_H_ -#define IOS_CHROME_BROWSER_UI_FULLSCREEN_VOICE_OVER_FULLSCREEN_DISABLER_H_ - -#import <UIKit/UIKit.h> - -class FullscreenController; - -// Helper class that handles disabling fullscreen while VoiceOver is enabled. -@interface VoiceOverFullscreenDisabler : NSObject - -- (nullable instancetype)initWithController: - (nonnull FullscreenController*)controller NS_DESIGNATED_INITIALIZER; -- (nullable instancetype)init NS_UNAVAILABLE; - -// Stops observing VoiceOver notifications. -- (void)disconnect; - -@end - -#endif // IOS_CHROME_BROWSER_UI_FULLSCREEN_VOICE_OVER_FULLSCREEN_DISABLER_H_
diff --git a/ios/chrome/browser/ui/fullscreen/voice_over_fullscreen_disabler.mm b/ios/chrome/browser/ui/fullscreen/voice_over_fullscreen_disabler.mm deleted file mode 100644 index 7cae7336..0000000 --- a/ios/chrome/browser/ui/fullscreen/voice_over_fullscreen_disabler.mm +++ /dev/null
@@ -1,72 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/fullscreen/voice_over_fullscreen_disabler.h" - -#include "base/logging.h" -#include "base/memory/ptr_util.h" -#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller.h" -#import "ios/chrome/browser/ui/fullscreen/scoped_fullscreen_disabler.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@interface VoiceOverFullscreenDisabler () { - // The disabler created when VoiceOver is enabled. - std::unique_ptr<ScopedFullscreenDisabler> _disabler; -} -// The FullscreenController being enabled/disabled for VoiceOver. -@property(nonatomic, readonly, nonnull) FullscreenController* controller; -// Creates or destroys |_disabler| depending on whether VoiceOver is enabled. -- (void)voiceOverStatusChanged; -@end - -@implementation VoiceOverFullscreenDisabler -@synthesize controller = _controller; - -- (instancetype)initWithController:(FullscreenController*)controller { - if (self = [super init]) { - _controller = controller; - DCHECK(_controller); - if (@available(iOS 11, *)) { - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(voiceOverStatusChanged) - name:UIAccessibilityVoiceOverStatusDidChangeNotification - object:nil]; - } else { - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(voiceOverStatusChanged) - name:UIAccessibilityVoiceOverStatusChanged - object:nil]; - } - if (UIAccessibilityIsVoiceOverRunning()) - _disabler = base::MakeUnique<ScopedFullscreenDisabler>(_controller); - } - return self; -} - -- (void)dealloc { - // |-disconnect| should be called before deallocation. - DCHECK(!_controller); -} - -#pragma mark Public - -- (void)disconnect { - [[NSNotificationCenter defaultCenter] removeObserver:self]; - _controller = nullptr; -} - -#pragma mark Private - -- (void)voiceOverStatusChanged { - _disabler = UIAccessibilityIsVoiceOverRunning() - ? base::MakeUnique<ScopedFullscreenDisabler>(_controller) - : nullptr; -} - -@end
diff --git a/ios/chrome/browser/ui/history/history_collection_view_controller.mm b/ios/chrome/browser/ui/history/history_collection_view_controller.mm index b7332708..7219ca8 100644 --- a/ios/chrome/browser/ui/history/history_collection_view_controller.mm +++ b/ios/chrome/browser/ui/history/history_collection_view_controller.mm
@@ -203,6 +203,13 @@ UIEdgeInsetsMake(0, kSeparatorInset, 0, kSeparatorInset); self.styler.allowsItemInlay = NO; + // Never adjust the content inset on iOS11 or it will create padding on top of + // the first cell. + if (@available(iOS 11, *)) { + [self.collectionView setContentInsetAdjustmentBehavior: + UIScrollViewContentInsetAdjustmentNever]; + } + self.clearsSelectionOnViewWillAppear = NO; self.collectionView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag; @@ -645,21 +652,20 @@ self.isSearching ? l10n_util::GetNSString(IDS_HISTORY_NO_SEARCH_RESULTS) : l10n_util::GetNSString(IDS_HISTORY_NO_RESULTS); entriesStatusItem = noResultsItem; - } else { + } else if (self.shouldShowNoticeAboutOtherFormsOfBrowsingHistory) { HistoryEntriesStatusItem* historyEntriesStatusItem = [[HistoryEntriesStatusItem alloc] initWithType:ItemTypeEntriesStatus]; historyEntriesStatusItem.delegate = self; historyEntriesStatusItem.hidden = self.isSearching; - historyEntriesStatusItem.showsOtherBrowsingDataNotice = - _shouldShowNoticeAboutOtherFormsOfBrowsingHistory; entriesStatusItem = historyEntriesStatusItem; } - // Replace the item in the first section, which is always present. + // Replace the item in the first section if it exists. Then insert the new + // item if it exists. NSArray* items = [self.collectionViewModel itemsInSectionWithIdentifier:kEntriesStatusSectionIdentifier]; if ([items count]) { - // There should only ever be one item in this section. - DCHECK([items count] == 1); + // There should only ever be at most one item in this section. + DCHECK([items count] <= 1); // Only update if the item has changed. if ([items[0] isEqual:entriesStatusItem]) { return; @@ -674,9 +680,11 @@ fromSectionWithIdentifier:kEntriesStatusSectionIdentifier]; [self.collectionView deleteItemsAtIndexPaths:@[ indexPath ]]; } - [self.collectionViewModel addItem:entriesStatusItem - toSectionWithIdentifier:kEntriesStatusSectionIdentifier]; - [self.collectionView insertItemsAtIndexPaths:@[ indexPath ]]; + if (entriesStatusItem) { + [self.collectionViewModel addItem:entriesStatusItem + toSectionWithIdentifier:kEntriesStatusSectionIdentifier]; + [self.collectionView insertItemsAtIndexPaths:@[ indexPath ]]; + } } completion:nil]; }
diff --git a/ios/chrome/browser/ui/history/history_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/history/history_collection_view_controller_unittest.mm index 803ade98..85bee1ee 100644 --- a/ios/chrome/browser/ui/history/history_collection_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/history/history_collection_view_controller_unittest.mm
@@ -160,9 +160,8 @@ scrollPosition:UICollectionViewScrollPositionNone]; [history_collection_view_controller_ deleteSelectedItemsFromHistory]; - // Expect header section with one item and one entries section with one item. + // Expect header section and one entries section with one item. EXPECT_EQ(2, [collection_view numberOfSections]); - EXPECT_EQ(1, [collection_view numberOfItemsInSection:0]); EXPECT_EQ(1, [collection_view numberOfItemsInSection:1]); } @@ -189,7 +188,6 @@ // Expect only the header section to remain. EXPECT_EQ(1, [collection_view numberOfSections]); - EXPECT_EQ(1, [collection_view numberOfItemsInSection:0]); } // Tests that adding two entries to history from different days then deleting @@ -217,5 +215,4 @@ // Expect only the header section to remain. EXPECT_EQ(1, [collection_view numberOfSections]); - EXPECT_EQ(1, [collection_view numberOfItemsInSection:0]); }
diff --git a/ios/chrome/browser/ui/history/history_entries_status_item.h b/ios/chrome/browser/ui/history/history_entries_status_item.h index 2a0e80ec..c11fdba 100644 --- a/ios/chrome/browser/ui/history/history_entries_status_item.h +++ b/ios/chrome/browser/ui/history/history_entries_status_item.h
@@ -25,8 +25,6 @@ @interface HistoryEntriesStatusItem : CollectionViewItem // YES if messages should be hidden. @property(nonatomic, assign, getter=isHidden) BOOL hidden; -// YES if message for other forms of browsing data should be shown. -@property(nonatomic, assign) BOOL showsOtherBrowsingDataNotice; // Delegate for HistoryEntriesStatusItem. Is notified when a link is pressed. @property(nonatomic, weak) id<HistoryEntriesStatusItemDelegate> delegate; @end
diff --git a/ios/chrome/browser/ui/history/history_entries_status_item.mm b/ios/chrome/browser/ui/history/history_entries_status_item.mm index 2a95ab5..280f3e1 100644 --- a/ios/chrome/browser/ui/history/history_entries_status_item.mm +++ b/ios/chrome/browser/ui/history/history_entries_status_item.mm
@@ -44,16 +44,6 @@ @implementation HistoryEntriesStatusItem @synthesize delegate = _delegate; @synthesize hidden = _hidden; -@synthesize showsOtherBrowsingDataNotice = _showsOtherBrowsingDataNotice; - -- (instancetype)initWithType:(NSInteger)type { - self = [super initWithType:type]; - if (self) { - _hidden = NO; - _showsOtherBrowsingDataNotice = NO; - } - return self; -} - (Class)cellClass { return [HistoryEntriesStatusCell class]; @@ -62,7 +52,7 @@ - (void)configureCell:(HistoryEntriesStatusCell*)cell { [super configureCell:cell]; [cell setDelegate:self]; - if (self.hidden || !self.showsOtherBrowsingDataNotice) { + if (self.hidden) { cell.textLabel.text = nil; } else { cell.textLabel.text = @@ -78,8 +68,7 @@ } - (BOOL)isEqualToHistoryEntriesStatusItem:(HistoryEntriesStatusItem*)object { - return self.hidden == object.hidden && - self.showsOtherBrowsingDataNotice == self.showsOtherBrowsingDataNotice; + return self.hidden == object.hidden; } - (BOOL)isEqual:(id)object {
diff --git a/ios/chrome/browser/ui/history/history_entries_status_item_unittest.mm b/ios/chrome/browser/ui/history/history_entries_status_item_unittest.mm index d72a38dc8..7706e87e 100644 --- a/ios/chrome/browser/ui/history/history_entries_status_item_unittest.mm +++ b/ios/chrome/browser/ui/history/history_entries_status_item_unittest.mm
@@ -50,39 +50,16 @@ using HistoryEntriesStatusItemTest = PlatformTest; // Tests that configuring a cell for HistoryEntriesStatusItem with hidden -// property set to YES results in an empty label, regardless of what -// showsOtherBrowsingDataNotice is set to. +// property set to YES results in an empty label. TEST_F(HistoryEntriesStatusItemTest, TestHidden) { HistoryEntriesStatusItem* item = [[HistoryEntriesStatusItem alloc] initWithType:0]; item.hidden = YES; - item.showsOtherBrowsingDataNotice = YES; HistoryEntriesStatusCell* cell = [[HistoryEntriesStatusCell alloc] init]; [item configureCell:cell]; EXPECT_FALSE(cell.textLabel.text); } -// Tests that configuring a cell for HistoryEntriesStatusItem with -// showsOtherBrowsingDataNotice set to YES adds other browsing -// data text to the label, while set to NO has no text. -TEST_F(HistoryEntriesStatusItemTest, TestOtherBrowsingDataNotice) { - HistoryEntriesStatusItem* item = - [[HistoryEntriesStatusItem alloc] initWithType:0]; - HistoryEntriesStatusCell* cell = [[HistoryEntriesStatusCell alloc] init]; - item.hidden = NO; - item.showsOtherBrowsingDataNotice = YES; - [item configureCell:cell]; - NSString* label_text = - l10n_util::GetNSString(IDS_IOS_HISTORY_OTHER_FORMS_OF_HISTORY); - NSRange range; - label_text = ParseStringWithLink(label_text, &range); - EXPECT_NSEQ(label_text, cell.textLabel.text); - - item.showsOtherBrowsingDataNotice = NO; - [item configureCell:cell]; - EXPECT_NSEQ(nil, cell.textLabel.text); -} - // Tests that tapping on links on a configured cell invokes // the HistoryEntriesStatusItemDelegate method. TEST_F(HistoryEntriesStatusItemTest, TestDelegate) { @@ -93,7 +70,6 @@ [[MockEntriesStatusItemDelegate alloc] init]; item.delegate = delegate; item.hidden = NO; - item.showsOtherBrowsingDataNotice = YES; [item configureCell:cell]; // Layout the cell so that links are drawn.
diff --git a/ios/chrome/browser/ui/main/BUILD.gn b/ios/chrome/browser/ui/main/BUILD.gn index c03590b..2066f74e8 100644 --- a/ios/chrome/browser/ui/main/BUILD.gn +++ b/ios/chrome/browser/ui/main/BUILD.gn
@@ -25,7 +25,6 @@ "//ios/chrome/browser/browsing_data:browsing_data_internal", "//ios/chrome/browser/crash_report:crash_report_internal", "//ios/chrome/browser/device_sharing", - "//ios/chrome/browser/physical_web", "//ios/chrome/browser/sessions", "//ios/chrome/browser/sessions:serialisation", "//ios/chrome/browser/tabs",
diff --git a/ios/chrome/browser/ui/main/browser_view_wrangler.mm b/ios/chrome/browser/ui/main/browser_view_wrangler.mm index 4abc557..2d6f5167 100644 --- a/ios/chrome/browser/ui/main/browser_view_wrangler.mm +++ b/ios/chrome/browser/ui/main/browser_view_wrangler.mm
@@ -11,7 +11,6 @@ #include "ios/chrome/browser/browsing_data/ios_chrome_browsing_data_remover.h" #include "ios/chrome/browser/crash_report/crash_report_helper.h" #import "ios/chrome/browser/device_sharing/device_sharing_manager.h" -#import "ios/chrome/browser/physical_web/start_physical_web_discovery.h" #import "ios/chrome/browser/sessions/session_ios.h" #import "ios/chrome/browser/sessions/session_service_ios.h" #import "ios/chrome/browser/sessions/session_window_ios.h" @@ -213,12 +212,6 @@ // The internal state of the Handoff Manager depends on the current BVC. [self updateDeviceSharingManager]; - - // By default, Physical Web discovery will not be started if the browser - // launches into an Incognito tab. On switching modes, check if discovery - // should be started. - StartPhysicalWebDiscovery(GetApplicationContext()->GetLocalState(), - [self currentBrowserState]); } #pragma mark - BrowserViewInformation methods
diff --git a/ios/chrome/browser/ui/main_content/main_content_ui_state.mm b/ios/chrome/browser/ui/main_content/main_content_ui_state.mm index 76cbf2f..177fce0e 100644 --- a/ios/chrome/browser/ui/main_content/main_content_ui_state.mm +++ b/ios/chrome/browser/ui/main_content/main_content_ui_state.mm
@@ -91,6 +91,11 @@ - (void)scrollViewDidEndDraggingWithGesture:(UIPanGestureRecognizer*)panGesture residualVelocity:(CGPoint)velocity { + // It's possible during the side-swipe gesture for a drag to end on the scroll + // view without a corresponding begin dragging call. Early return if there + // is no pan gesture from the begin call. + if (!self.panGesture) + return; DCHECK_EQ(panGesture, self.panGesture); if (!AreCGFloatsEqual(velocity.y, 0.0)) self.state.decelerating = YES;
diff --git a/ios/chrome/browser/ui/main_content/web_scroll_view_main_content_ui_forwarder.mm b/ios/chrome/browser/ui/main_content/web_scroll_view_main_content_ui_forwarder.mm index 936f8d0..5ec6ab8 100644 --- a/ios/chrome/browser/ui/main_content/web_scroll_view_main_content_ui_forwarder.mm +++ b/ios/chrome/browser/ui/main_content/web_scroll_view_main_content_ui_forwarder.mm
@@ -109,6 +109,14 @@ #pragma mark - WebStateListObserving - (void)webStateList:(WebStateList*)webStateList + didReplaceWebState:(web::WebState*)oldWebState + withWebState:(web::WebState*)newWebState + atIndex:(int)atIndex { + if (newWebState == webStateList->GetActiveWebState()) + self.proxy = newWebState->GetWebViewProxy().scrollViewProxy; +} + +- (void)webStateList:(WebStateList*)webStateList didChangeActiveWebState:(web::WebState*)newWebState oldWebState:(web::WebState*)oldWebState atIndex:(int)atIndex
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn index b2c509e..0e468be 100644 --- a/ios/chrome/browser/ui/settings/BUILD.gn +++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -43,8 +43,6 @@ "password_details_collection_view_controller.h", "password_details_collection_view_controller.mm", "password_details_collection_view_controller_delegate.h", - "physical_web_collection_view_controller.h", - "physical_web_collection_view_controller.mm", "privacy_collection_view_controller.h", "privacy_collection_view_controller.mm", "reauthentication_module.h", @@ -101,7 +99,6 @@ "//components/metrics", "//components/password_manager/core/browser", "//components/password_manager/core/common", - "//components/physical_web/data_source", "//components/resources", "//components/search_engines", "//components/signin/core/browser", @@ -123,7 +120,6 @@ "//ios/chrome/browser/feature_engagement", "//ios/chrome/browser/history", "//ios/chrome/browser/passwords", - "//ios/chrome/browser/physical_web", "//ios/chrome/browser/prefs", "//ios/chrome/browser/search_engines", "//ios/chrome/browser/signin", @@ -229,7 +225,6 @@ "do_not_track_collection_view_controller_unittest.mm", "import_data_collection_view_controller_unittest.mm", "password_details_collection_view_controller_unittest.mm", - "physical_web_collection_view_controller_unittest.mm", "privacy_collection_view_controller_unittest.mm", "save_passwords_collection_view_controller_unittest.mm", "search_engine_settings_collection_view_controller_unittest.mm", @@ -274,7 +269,6 @@ "//ios/chrome/browser/browsing_data", "//ios/chrome/browser/content_settings", "//ios/chrome/browser/passwords", - "//ios/chrome/browser/physical_web", "//ios/chrome/browser/prefs:browser_prefs", "//ios/chrome/browser/search_engines", "//ios/chrome/browser/signin",
diff --git a/ios/chrome/browser/ui/settings/physical_web_collection_view_controller.h b/ios/chrome/browser/ui/settings/physical_web_collection_view_controller.h deleted file mode 100644 index eb82c04..0000000 --- a/ios/chrome/browser/ui/settings/physical_web_collection_view_controller.h +++ /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. - -#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_PHYSICAL_WEB_COLLECTION_VIEW_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_SETTINGS_PHYSICAL_WEB_COLLECTION_VIEW_CONTROLLER_H_ - -#import "ios/chrome/browser/ui/settings/settings_root_collection_view_controller.h" - -#include "components/prefs/pref_service.h" - -// This View Controller is responsible for managing the settings related to -// the Physical Web. -@interface PhysicalWebCollectionViewController - : SettingsRootCollectionViewController - -// The designated initializer. -- (instancetype)initWithPrefs:(PrefService*)prefs NS_DESIGNATED_INITIALIZER; - -- (instancetype)init NS_UNAVAILABLE; - -- (instancetype)initWithLayout:(UICollectionViewLayout*)layout - style:(CollectionViewControllerStyle)style - NS_UNAVAILABLE; - -// Given the current Physical Web preference state, determine whether the -// preference should be rendered as enabled. -+ (BOOL)shouldEnableForPreferenceState:(int)preferenceState; - -@end - -#endif // IOS_CHROME_BROWSER_UI_SETTINGS_PHYSICAL_WEB_COLLECTION_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/physical_web_collection_view_controller.mm b/ios/chrome/browser/ui/settings/physical_web_collection_view_controller.mm deleted file mode 100644 index 8c28431..0000000 --- a/ios/chrome/browser/ui/settings/physical_web_collection_view_controller.mm +++ /dev/null
@@ -1,238 +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. - -#import "ios/chrome/browser/ui/settings/physical_web_collection_view_controller.h" - -#import <CoreLocation/CoreLocation.h> - -#import "base/mac/foundation_util.h" -#include "base/metrics/user_metrics.h" -#include "components/google/core/browser/google_util.h" -#include "components/physical_web/data_source/physical_web_data_source.h" -#include "components/prefs/pref_member.h" -#include "ios/chrome/browser/application_context.h" -#include "ios/chrome/browser/chrome_url_constants.h" -#include "ios/chrome/browser/physical_web/physical_web_constants.h" -#include "ios/chrome/browser/pref_names.h" -#import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h" -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_footer_item.h" -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h" -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_switch_item.h" -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h" -#import "ios/chrome/browser/ui/collection_view/collection_view_model.h" -#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" -#import "ios/chrome/browser/ui/settings/settings_utils.h" -#import "ios/chrome/common/string_util.h" -#include "ios/chrome/grit/ios_chromium_strings.h" -#include "ios/chrome/grit/ios_strings.h" -#import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h" -#include "ui/base/l10n/l10n_util.h" -#include "url/gurl.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { - -typedef NS_ENUM(NSInteger, SectionIdentifier) { - SectionIdentifierPhysicalWeb = kSectionIdentifierEnumZero, - SectionIdentifierLearnMore, -}; - -typedef NS_ENUM(NSInteger, ItemType) { - ItemTypePhysicalWebSwitch = kItemTypeEnumZero, - ItemTypeLearnMore, -}; - -} // namespace - -@interface PhysicalWebCollectionViewController () { - // Pref for the Physical Web enabled state. - IntegerPrefMember _physicalWebEnabled; -} - -// Called when the preference switch is toggled on or off. -- (void)physicalWebSwitched:(UISwitch*)switchView; - -// Updates the Physical Web preference. -- (void)updatePhysicalWebEnabled:(BOOL)enabled; -@end - -@implementation PhysicalWebCollectionViewController - -#pragma mark - Initialization - -- (instancetype)initWithPrefs:(PrefService*)prefs { - UICollectionViewLayout* layout = [[MDCCollectionViewFlowLayout alloc] init]; - self = - [super initWithLayout:layout style:CollectionViewControllerStyleAppBar]; - if (self) { - self.title = l10n_util::GetNSString(IDS_IOS_OPTIONS_ENABLE_PHYSICAL_WEB); - _physicalWebEnabled.Init(prefs::kIosPhysicalWebEnabled, prefs); - // TODO(crbug.com/764578): -loadModel should not be called from - // initializer. A possible fix is to move this call to -viewDidLoad. - [self loadModel]; - } - return self; -} - -#pragma mark - Preference switch - -+ (BOOL)shouldEnableForPreferenceState:(int)preferenceState { - // Render the preference as "on" only if the preference is explicitly enabled. - return (preferenceState == physical_web::kPhysicalWebOn); -} - -- (void)physicalWebSwitched:(UISwitch*)switchView { - [self updatePhysicalWebEnabled:switchView.isOn]; -} - -- (void)updatePhysicalWebEnabled:(BOOL)enabled { - _physicalWebEnabled.SetValue(enabled ? physical_web::kPhysicalWebOn - : physical_web::kPhysicalWebOff); - - physical_web::PhysicalWebDataSource* dataSource = - GetApplicationContext()->GetPhysicalWebDataSource(); - - if (enabled) { - base::RecordAction( - base::UserMetricsAction("PhysicalWeb.Prefs.FeatureEnabled")); - if (dataSource) { - dataSource->StartDiscovery(true); - } - } else { - base::RecordAction( - base::UserMetricsAction("PhysicalWeb.Prefs.FeatureDisabled")); - if (dataSource) { - dataSource->StopDiscovery(); - } - } -} - -#pragma mark - UICollectionViewDataSource - -- (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView - cellForItemAtIndexPath:(NSIndexPath*)indexPath { - UICollectionViewCell* cell = - [super collectionView:collectionView cellForItemAtIndexPath:indexPath]; - - NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath]; - switch (type) { - case ItemTypePhysicalWebSwitch: { - CollectionViewSwitchCell* switchCell = - base::mac::ObjCCastStrict<CollectionViewSwitchCell>(cell); - [switchCell.switchView addTarget:self - action:@selector(physicalWebSwitched:) - forControlEvents:UIControlEventValueChanged]; - break; - } - } - - return cell; -} - -#pragma mark - UICollectionViewDelegate - -- (BOOL)collectionView:(UICollectionView*)collectionView - shouldHighlightItemAtIndexPath:(NSIndexPath*)indexPath { - NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath]; - switch (type) { - case ItemTypePhysicalWebSwitch: - case ItemTypeLearnMore: - return NO; - default: - return [super collectionView:collectionView - shouldHighlightItemAtIndexPath:indexPath]; - } -} - -#pragma mark - SettingsRootCollectionViewController - -- (void)loadModel { - [super loadModel]; - CollectionViewModel* model = self.collectionViewModel; - - [model addSectionWithIdentifier:SectionIdentifierPhysicalWeb]; - - NSString* switchLabelText = - l10n_util::GetNSString(IDS_IOS_OPTIONS_ENABLE_PHYSICAL_WEB); - - CollectionViewSwitchItem* switchItem = - [[CollectionViewSwitchItem alloc] initWithType:ItemTypePhysicalWebSwitch]; - switchItem.text = switchLabelText; - switchItem.on = [PhysicalWebCollectionViewController - shouldEnableForPreferenceState:_physicalWebEnabled.GetValue()]; - [model addItem:switchItem - toSectionWithIdentifier:SectionIdentifierPhysicalWeb]; - - [model addSectionWithIdentifier:SectionIdentifierLearnMore]; - - NSString* learnMoreText = - l10n_util::GetNSString(IDS_IOS_OPTIONS_ENABLE_PHYSICAL_WEB_DETAILS); - - CollectionViewFooterItem* learnMore = - [[CollectionViewFooterItem alloc] initWithType:ItemTypeLearnMore]; - learnMore.text = learnMoreText; - learnMore.linkURL = GURL(kPhysicalWebLearnMoreURL); - learnMore.linkDelegate = self; - learnMore.accessibilityTraits = UIAccessibilityTraitButton; - [model addItem:learnMore toSectionWithIdentifier:SectionIdentifierLearnMore]; -} - -#pragma mark - MDCCollectionViewStylingDelegate - -- (MDCCollectionViewCellStyle)collectionView:(UICollectionView*)collectionView - cellStyleForSection:(NSInteger)section { - NSInteger sectionIdentifier = - [self.collectionViewModel sectionIdentifierForSection:section]; - switch (sectionIdentifier) { - case SectionIdentifierLearnMore: - // Display the Learn More footer in the default style with no "card" UI - // and no section padding. - return MDCCollectionViewCellStyleDefault; - default: - return self.styler.cellStyle; - } -} - -- (CGFloat)collectionView:(UICollectionView*)collectionView - cellHeightAtIndexPath:(NSIndexPath*)indexPath { - CollectionViewItem* item = - [self.collectionViewModel itemAtIndexPath:indexPath]; - switch (item.type) { - case ItemTypeLearnMore: - return [MDCCollectionViewCell - cr_preferredHeightForWidth:CGRectGetWidth(collectionView.bounds) - forItem:item]; - default: - return MDCCellDefaultOneLineHeight; - } -} - -- (BOOL)collectionView:(UICollectionView*)collectionView - shouldHideItemBackgroundAtIndexPath:(NSIndexPath*)indexPath { - NSInteger sectionIdentifier = - [self.collectionViewModel sectionIdentifierForSection:indexPath.section]; - switch (sectionIdentifier) { - case SectionIdentifierLearnMore: - // Display the Learn More footer without any background image or - // shadowing. - return YES; - default: - return NO; - } -} -- (BOOL)collectionView:(UICollectionView*)collectionView - hidesInkViewAtIndexPath:(NSIndexPath*)indexPath { - NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath]; - switch (type) { - case ItemTypePhysicalWebSwitch: - return YES; - default: - return NO; - } -} - -@end
diff --git a/ios/chrome/browser/ui/settings/physical_web_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/physical_web_collection_view_controller_unittest.mm deleted file mode 100644 index e946236..0000000 --- a/ios/chrome/browser/ui/settings/physical_web_collection_view_controller_unittest.mm +++ /dev/null
@@ -1,90 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/settings/physical_web_collection_view_controller.h" - -#include <memory> - -#include "base/files/file_path.h" -#include "base/memory/ptr_util.h" -#include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop.h" -#include "components/prefs/pref_registry_simple.h" -#include "components/prefs/pref_service.h" -#include "components/sync_preferences/pref_service_mock_factory.h" -#include "ios/chrome/browser/physical_web/physical_web_constants.h" -#include "ios/chrome/browser/pref_names.h" -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_footer_item.h" -#import "ios/chrome/browser/ui/collection_view/cells/collection_view_switch_item.h" -#import "ios/chrome/browser/ui/collection_view/collection_view_controller_test.h" -#include "ios/chrome/grit/ios_chromium_strings.h" -#include "ios/chrome/grit/ios_strings.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@interface PhysicalWebCollectionViewController (ExposedForTesting) -- (void)updatePhysicalWebEnabled:(BOOL)enabled; -@end - -namespace { - -class PhysicalWebCollectionViewControllerTest - : public CollectionViewControllerTest { - protected: - void SetUp() override { - CollectionViewControllerTest::SetUp(); - pref_service_ = CreateLocalState(); - CreateController(); - } - - CollectionViewController* InstantiateController() override { - physicalWebController_ = [[PhysicalWebCollectionViewController alloc] - initWithPrefs:pref_service_.get()]; - return physicalWebController_; - } - - std::unique_ptr<PrefService> CreateLocalState() { - scoped_refptr<PrefRegistrySimple> registry(new PrefRegistrySimple()); - registry->RegisterIntegerPref(prefs::kIosPhysicalWebEnabled, - physical_web::kPhysicalWebOnboarding); - - sync_preferences::PrefServiceMockFactory factory; - base::FilePath path("PhysicalWebCollectionViewControllerTest.pref"); - factory.SetUserPrefsFile(path, message_loop_.task_runner().get()); - return factory.Create(registry.get()); - } - - base::MessageLoopForUI message_loop_; - std::unique_ptr<PrefService> pref_service_; - PhysicalWebCollectionViewController* physicalWebController_; -}; - -// Tests PhysicalWebCollectionViewController is set up with all appropriate -// items and sections. -TEST_F(PhysicalWebCollectionViewControllerTest, TestModel) { - CheckController(); - EXPECT_EQ(2, NumberOfSections()); - - // First section should have no section header and one row (switch item). - EXPECT_EQ(1, NumberOfItemsInSection(0)); - CheckSwitchCellStateAndTitleWithId(NO, IDS_IOS_OPTIONS_ENABLE_PHYSICAL_WEB, 0, - 0); - - // Section section should have no section header and one row (footer item). - EXPECT_EQ(1, NumberOfItemsInSection(1)); - CheckSectionFooterWithId(IDS_IOS_OPTIONS_ENABLE_PHYSICAL_WEB_DETAILS, 1); -} - -TEST_F(PhysicalWebCollectionViewControllerTest, TestUpdateCheckedState) { - CheckController(); - ASSERT_EQ(2, NumberOfSections()); - ASSERT_EQ(1, NumberOfItemsInSection(0)); - - [physicalWebController_ - updatePhysicalWebEnabled:physical_web::kPhysicalWebOn]; -} - -} // namespace
diff --git a/ios/chrome/browser/ui/settings/privacy_collection_view_controller.mm b/ios/chrome/browser/ui/settings/privacy_collection_view_controller.mm index 5e523ef..a7f5c0e 100644 --- a/ios/chrome/browser/ui/settings/privacy_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/privacy_collection_view_controller.mm
@@ -21,7 +21,6 @@ #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/chrome_url_constants.h" #include "ios/chrome/browser/experimental_flags.h" -#include "ios/chrome/browser/physical_web/physical_web_constants.h" #include "ios/chrome/browser/pref_names.h" #import "ios/chrome/browser/prefs/pref_observer_bridge.h" #import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h" @@ -35,7 +34,6 @@ #import "ios/chrome/browser/ui/settings/dataplan_usage_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/do_not_track_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/handoff_collection_view_controller.h" -#import "ios/chrome/browser/ui/settings/physical_web_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" #import "ios/chrome/browser/ui/settings/settings_utils.h" #import "ios/chrome/browser/ui/settings/utils/pref_backed_boolean.h" @@ -71,7 +69,6 @@ ItemTypeWebServicesShowSuggestions, ItemTypeWebServicesSendUsageData, ItemTypeWebServicesDoNotTrack, - ItemTypeWebServicesPhysicalWeb, ItemTypeClearBrowsingDataClear, }; @@ -101,7 +98,6 @@ - (CollectionViewItem*)showSuggestionsFooterItem; - (CollectionViewItem*)clearBrowsingDetailItem; - (CollectionViewItem*)sendUsageDetailItem; -- (CollectionViewItem*)physicalWebDetailItem; - (CollectionViewItem*)doNotTrackDetailItem; @end @@ -193,11 +189,6 @@ toSectionWithIdentifier:SectionIdentifierWebServices]; } - if (experimental_flags::IsPhysicalWebEnabled()) { - [model addItem:[self physicalWebDetailItem] - toSectionWithIdentifier:SectionIdentifierWebServices]; - } - // Footer Section [model addSectionWithIdentifier:SectionIdentifierWebServicesFooter]; [model addItem:[self showSuggestionsFooterItem] @@ -267,18 +258,6 @@ return _sendUsageDetailItem; } -- (CollectionViewItem*)physicalWebDetailItem { - PrefService* prefService = GetApplicationContext()->GetLocalState(); - int preferenceState = prefService->GetInteger(prefs::kIosPhysicalWebEnabled); - BOOL enabled = [PhysicalWebCollectionViewController - shouldEnableForPreferenceState:preferenceState]; - NSString* detailText = enabled ? l10n_util::GetNSString(IDS_IOS_SETTING_ON) - : l10n_util::GetNSString(IDS_IOS_SETTING_OFF); - return [self detailItemWithType:ItemTypeWebServicesPhysicalWeb - titleId:IDS_IOS_OPTIONS_ENABLE_PHYSICAL_WEB - detailText:detailText]; -} - - (CollectionViewItem*)doNotTrackDetailItem { NSString* detailText = _browserState->GetPrefs()->GetBoolean(prefs::kEnableDoNotTrack) @@ -350,10 +329,6 @@ controller = [[DoNotTrackCollectionViewController alloc] initWithPrefs:_browserState->GetPrefs()]; break; - case ItemTypeWebServicesPhysicalWeb: - controller = [[PhysicalWebCollectionViewController alloc] - initWithPrefs:GetApplicationContext()->GetLocalState()]; - break; case ItemTypeClearBrowsingDataClear: controller = [[ClearBrowsingDataCollectionViewController alloc] initWithBrowserState:_browserState];
diff --git a/ios/chrome/browser/ui/settings/privacy_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/privacy_collection_view_controller_unittest.mm index a5742d53..2e122fa 100644 --- a/ios/chrome/browser/ui/settings/privacy_collection_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/privacy_collection_view_controller_unittest.mm
@@ -20,7 +20,6 @@ #include "ios/chrome/browser/pref_names.h" #include "ios/chrome/browser/prefs/browser_prefs.h" #import "ios/chrome/browser/ui/collection_view/collection_view_controller_test.h" -#import "ios/chrome/browser/ui/settings/physical_web_collection_view_controller.h" #include "ios/chrome/grit/ios_chromium_strings.h" #include "ios/chrome/grit/ios_strings.h" #include "ios/chrome/test/ios_chrome_scoped_testing_local_state.h" @@ -107,8 +106,6 @@ if (web::IsDoNotTrackSupported()) expectedRows++; - if (experimental_flags::IsPhysicalWebEnabled()) - expectedRows++; EXPECT_EQ(expectedRows, NumberOfItemsInSection(sectionIndex)); CheckSectionHeaderWithId(IDS_IOS_OPTIONS_WEB_SERVICES_LABEL, sectionIndex); @@ -130,19 +127,6 @@ l10n_util::GetNSString(IDS_IOS_OPTIONS_DO_NOT_TRACK_MOBILE), doNotTrackSubtitle, sectionIndex, row++); } - if (experimental_flags::IsPhysicalWebEnabled()) { - NSInteger physicalWebState = - GetApplicationContext()->GetLocalState()->GetInteger( - prefs::kIosPhysicalWebEnabled); - BOOL physicalWebEnabled = [PhysicalWebCollectionViewController - shouldEnableForPreferenceState:physicalWebState]; - NSString* physicalWebSubtitle = - physicalWebEnabled ? l10n_util::GetNSString(IDS_IOS_SETTING_ON) - : l10n_util::GetNSString(IDS_IOS_SETTING_OFF); - CheckTextCellTitleAndSubtitle( - l10n_util::GetNSString(IDS_IOS_OPTIONS_ENABLE_PHYSICAL_WEB), - physicalWebSubtitle, sectionIndex, row++); - } sectionIndex++; EXPECT_EQ(1, NumberOfItemsInSection(sectionIndex));
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher_transition_egtest.mm b/ios/chrome/browser/ui/tab_switcher/tab_switcher_transition_egtest.mm index ded8ecb..b564143 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_switcher_transition_egtest.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher_transition_egtest.mm
@@ -457,7 +457,7 @@ // Tests rotating the device while the switcher is not active. This is a // regression test case for https://crbug.com/789975. - (void)testRotationsWhileSwitcherIsNotActive { - NSString* tab_title = @"NormalTabLongerStringForTest1"; + NSString* tab_title = @"NormalTabLongerStringForRotationTest"; [self setUpTestServer]; [ChromeEarlGrey loadURL:[self makeURLForTitle:tab_title]];
diff --git a/ios/chrome/browser/ui/toolbar/legacy_toolbar_ui_updater.mm b/ios/chrome/browser/ui/toolbar/legacy_toolbar_ui_updater.mm index aae9a576..0ab6e0a1 100644 --- a/ios/chrome/browser/ui/toolbar/legacy_toolbar_ui_updater.mm +++ b/ios/chrome/browser/ui/toolbar/legacy_toolbar_ui_updater.mm
@@ -115,6 +115,15 @@ #pragma mark WebStateListObserving - (void)webStateList:(WebStateList*)webStateList + didReplaceWebState:(web::WebState*)oldWebState + withWebState:(web::WebState*)newWebState + atIndex:(int)atIndex { + DCHECK_EQ(self.webStateList, webStateList); + if (newWebState == webStateList->GetActiveWebState()) + self.webState = newWebState; +} + +- (void)webStateList:(WebStateList*)webStateList didChangeActiveWebState:(web::WebState*)newWebState oldWebState:(web::WebState*)oldWebState atIndex:(int)atIndex
diff --git a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm index ca69e6a..dbd6e91 100644 --- a/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm +++ b/ios/chrome/browser/ui/toolbar/web_toolbar_controller.mm
@@ -1915,7 +1915,9 @@ // The popup positions itself as a static frame below the web toolbar. This // will no longer be necessary post omnibox popup boxing. - _popupView->UpdatePopupAppearance(); + if (_popupView) { + _popupView->UpdatePopupAppearance(); + } } @end
diff --git a/ios/chrome/browser/ui/webui/BUILD.gn b/ios/chrome/browser/ui/webui/BUILD.gn index 016b19c..aafae11 100644 --- a/ios/chrome/browser/ui/webui/BUILD.gn +++ b/ios/chrome/browser/ui/webui/BUILD.gn
@@ -16,8 +16,6 @@ "ntp_tiles_internals_ui.h", "password_manager_internals_ui_ios.h", "password_manager_internals_ui_ios.mm", - "physical_web_ui.cc", - "physical_web_ui.h", "suggestions_ui.cc", "suggestions_ui.h", "terms_ui.h",
diff --git a/ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.mm b/ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.mm index 6b67b62..8f9ecbb 100644 --- a/ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.mm +++ b/ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.mm
@@ -17,7 +17,6 @@ #include "ios/chrome/browser/ui/webui/ntp_tiles_internals_ui.h" #include "ios/chrome/browser/ui/webui/omaha_ui.h" #include "ios/chrome/browser/ui/webui/password_manager_internals_ui_ios.h" -#include "ios/chrome/browser/ui/webui/physical_web_ui.h" #include "ios/chrome/browser/ui/webui/signin_internals_ui_ios.h" #include "ios/chrome/browser/ui/webui/suggestions_ui.h" #include "ios/chrome/browser/ui/webui/sync_internals/sync_internals_ui.h" @@ -79,10 +78,6 @@ return &NewWebUIIOS<OmahaUI>; if (url_host == kChromeUIPasswordManagerInternalsHost) return &NewWebUIIOS<PasswordManagerInternalsUIIOS>; - if (experimental_flags::IsPhysicalWebEnabled()) { - if (url_host == kChromeUIPhysicalWebHost) - return &NewWebUIIOS<PhysicalWebUI>; - } if (url_host == kChromeUISignInInternalsHost) return &NewWebUIIOS<SignInInternalsUIIOS>; if (url.host_piece() == kChromeUISuggestionsHost)
diff --git a/ios/chrome/browser/ui/webui/physical_web_ui.cc b/ios/chrome/browser/ui/webui/physical_web_ui.cc deleted file mode 100644 index 9f5b4e3..0000000 --- a/ios/chrome/browser/ui/webui/physical_web_ui.cc +++ /dev/null
@@ -1,112 +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 "ios/chrome/browser/ui/webui/physical_web_ui.h" - -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/metrics/user_metrics.h" -#include "components/grit/components_resources.h" -#include "components/physical_web/data_source/physical_web_data_source.h" -#include "components/physical_web/webui/physical_web_base_message_handler.h" -#include "components/physical_web/webui/physical_web_ui_constants.h" -#include "components/strings/grit/components_strings.h" -#include "ios/chrome/browser/application_context.h" -#include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#include "ios/chrome/browser/chrome_url_constants.h" -#include "ios/web/public/web_ui_ios_data_source.h" -#include "ios/web/public/webui/web_ui_ios.h" -#include "ios/web/public/webui/web_ui_ios_message_handler.h" - -namespace { - -web::WebUIIOSDataSource* CreatePhysicalWebUIDataSource() { - web::WebUIIOSDataSource* html_source = - web::WebUIIOSDataSource::Create(kChromeUIPhysicalWebHost); - - // Localized and data strings. - html_source->AddLocalizedString(physical_web_ui::kTitle, - IDS_PHYSICAL_WEB_UI_TITLE); - html_source->AddLocalizedString(physical_web_ui::kEmptyMessage, - IDS_PHYSICAL_WEB_UI_EMPTY_MESSAGE); - html_source->SetJsonPath("strings.js"); - html_source->AddResourcePath(physical_web_ui::kPhysicalWebJS, - IDR_PHYSICAL_WEB_UI_JS); - html_source->AddResourcePath(physical_web_ui::kPhysicalWebCSS, - IDR_PHYSICAL_WEB_UI_CSS); - html_source->AddResourcePath(physical_web_ui::kPhysicalWebLinkIcon, - IDR_PHYSICAL_WEB_UI_LINK_ICON); - html_source->SetDefaultResource(IDR_PHYSICAL_WEB_UI_HTML); - html_source->UseGzip(); - return html_source; -} - -// Implements all MessageHandler core functionality. This is extends the -// PhysicalWebBaseMessageHandler and implements functions to manipulate an -// iOS-specific WebUI object. -class MessageHandlerImpl - : public physical_web_ui::PhysicalWebBaseMessageHandler { - public: - explicit MessageHandlerImpl(web::WebUIIOS* web_ui) : web_ui_(web_ui) {} - ~MessageHandlerImpl() override {} - - private: - void RegisterMessageCallback( - const std::string& message, - const physical_web_ui::MessageCallback& callback) override { - web_ui_->RegisterMessageCallback(message, callback); - } - void CallJavaScriptFunction(const std::string& function, - const base::Value& arg) override { - web_ui_->CallJavascriptFunction(function, arg); - } - physical_web::PhysicalWebDataSource* GetPhysicalWebDataSource() override { - return GetApplicationContext()->GetPhysicalWebDataSource(); - } - - web::WebUIIOS* web_ui_; - DISALLOW_COPY_AND_ASSIGN(MessageHandlerImpl); -}; - -//////////////////////////////////////////////////////////////////////////////// -// -// PhysicalWebDOMHandler -// -//////////////////////////////////////////////////////////////////////////////// - -// The handler for Javascript messages for the chrome:physical-web page. -class PhysicalWebDOMHandler : public web::WebUIIOSMessageHandler { - public: - PhysicalWebDOMHandler() {} - ~PhysicalWebDOMHandler() override {} - - void RegisterMessages() override { - impl_.reset(new MessageHandlerImpl(web_ui())); - impl_->RegisterMessages(); - } - - private: - std::unique_ptr<MessageHandlerImpl> impl_; - DISALLOW_COPY_AND_ASSIGN(PhysicalWebDOMHandler); -}; - -} // namespace - -//////////////////////////////////////////////////////////////////////////////// -// -// PhysicalWebUI -// -//////////////////////////////////////////////////////////////////////////////// - -PhysicalWebUI::PhysicalWebUI(web::WebUIIOS* web_ui) - : web::WebUIIOSController(web_ui) { - web_ui->AddMessageHandler(base::MakeUnique<PhysicalWebDOMHandler>()); - - web::WebUIIOSDataSource::Add(ios::ChromeBrowserState::FromWebUIIOS(web_ui), - CreatePhysicalWebUIDataSource()); - - base::RecordAction(base::UserMetricsAction("PhysicalWeb.WebUI.Open")); -} - -PhysicalWebUI::~PhysicalWebUI() {}
diff --git a/ios/chrome/browser/ui/webui/physical_web_ui.h b/ios/chrome/browser/ui/webui/physical_web_ui.h deleted file mode 100644 index 8fe669e..0000000 --- a/ios/chrome/browser/ui/webui/physical_web_ui.h +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_WEBUI_PHYSICAL_WEB_UI_H_ -#define IOS_CHROME_BROWSER_UI_WEBUI_PHYSICAL_WEB_UI_H_ - -#include <string> - -#include "base/macros.h" -#include "ios/web/public/webui/web_ui_ios_controller.h" - -// The WebUI handler for chrome://physical-web. -class PhysicalWebUI : public web::WebUIIOSController { - public: - explicit PhysicalWebUI(web::WebUIIOS* web_ui); - ~PhysicalWebUI() override; - - private: - DISALLOW_COPY_AND_ASSIGN(PhysicalWebUI); -}; - -#endif // IOS_CHROME_BROWSER_UI_WEBUI_PHYSICAL_WEB_UI_H_
diff --git a/ios/chrome/browser/ui/webui/web_ui_egtest.mm b/ios/chrome/browser/ui/webui/web_ui_egtest.mm index 030ac76..f14eca43 100644 --- a/ios/chrome/browser/ui/webui/web_ui_egtest.mm +++ b/ios/chrome/browser/ui/webui/web_ui_egtest.mm
@@ -94,20 +94,6 @@ [ChromeEarlGrey waitForWebViewContainingText:userAgent]; } -// Tests that chrome://physical-web renders and the page title is present. -// TODO(crbug.com/760104): Re-enable this test once physical web is re-enabled. -- (void)DISABLED_testPhysicalWeb { - // Enable the Physical Web via Chrome variation. - base::FieldTrialList::CreateFieldTrial("PhysicalWebEnabled", "Enabled"); - - LoadWebUIUrl(kChromeUIPhysicalWebHost); - - // Verify that the title string is present on the page. - const std::string pageTitle = - l10n_util::GetStringUTF8(IDS_PHYSICAL_WEB_UI_TITLE); - [ChromeEarlGrey waitForWebViewContainingText:pageTitle]; -} - // Tests that clicking on a chrome://terms link from chrome://chrome-urls // navigates to terms page. - (void)testChromeURLNavigateToTerms { @@ -180,10 +166,6 @@ if (host == kChromeUIBookmarksHost || host == kChromeUINewTabHost) { continue; } - if (host == kChromeUIPhysicalWebHost && - !experimental_flags::IsPhysicalWebEnabled()) { - continue; - } LoadWebUIUrl(host); const std::string chrome_url_path = url::SchemeHostPort(kChromeUIScheme, kChromeHostURLs[i], 0).Serialize();
diff --git a/ios/chrome/browser/web/push_and_replace_state_navigation_egtest.mm b/ios/chrome/browser/web/push_and_replace_state_navigation_egtest.mm index b67f2a08..431ad368 100644 --- a/ios/chrome/browser/web/push_and_replace_state_navigation_egtest.mm +++ b/ios/chrome/browser/web/push_and_replace_state_navigation_egtest.mm
@@ -59,40 +59,42 @@ // Push 3 URLs. Verify that the URL changed and the status was updated. [ChromeEarlGrey tapWebViewElementWithID:@"pushStateHashWithObject"]; [self assertStatusText:@"pushStateHashWithObject" - withURL:pushStateHashWithObjectURL + withOmniboxText:pushStateHashWithObjectURL.GetContent() pageLoaded:NO]; [ChromeEarlGrey tapWebViewElementWithID:@"pushStateRootPath"]; [self assertStatusText:@"pushStateRootPath" - withURL:pushStateRootPathURL + withOmniboxText:pushStateRootPathURL.GetContent() pageLoaded:NO]; [ChromeEarlGrey tapWebViewElementWithID:@"pushStatePathSpace"]; [self assertStatusText:@"pushStatePathSpace" - withURL:pushStatePathSpaceURL + withOmniboxText:pushStatePathSpaceURL.GetContent() pageLoaded:NO]; // Go back and check that the page doesn't load and the status text is updated // by the popstate event. [[EarlGrey selectElementWithMatcher:BackButton()] performAction:grey_tap()]; [self assertStatusText:@"pushStateRootPath" - withURL:pushStateRootPathURL + withOmniboxText:pushStateRootPathURL.GetContent() pageLoaded:NO]; [[EarlGrey selectElementWithMatcher:BackButton()] performAction:grey_tap()]; [self assertStatusText:@"pushStateHashWithObject" - withURL:pushStateHashWithObjectURL + withOmniboxText:pushStateHashWithObjectURL.GetContent() pageLoaded:NO]; [ChromeEarlGrey tapWebViewElementWithID:@"goBack"]; const GURL historyTestURL = web::test::HttpServer::MakeUrl(kHistoryTestUrl); - [self assertStatusText:NULL withURL:historyTestURL pageLoaded:NO]; + [self assertStatusText:nil + withOmniboxText:historyTestURL.GetContent() + pageLoaded:NO]; // Go forward 2 pages and check that the page doesn't load and the status text // is updated by the popstate event. [ChromeEarlGrey tapWebViewElementWithID:@"goForward2"]; [self assertStatusText:@"pushStateRootPath" - withURL:pushStateRootPathURL + withOmniboxText:pushStateRootPathURL.GetContent() pageLoaded:NO]; } @@ -108,7 +110,7 @@ web::test::HttpServer::MakeUrl(kReplaceStateHashWithObjectURL); [ChromeEarlGrey tapWebViewElementWithID:@"replaceStateHashWithObject"]; [self assertStatusText:@"replaceStateHashWithObject" - withURL:replaceStateHashWithObjectURL + withOmniboxText:replaceStateHashWithObjectURL.GetContent() pageLoaded:NO]; [[EarlGrey selectElementWithMatcher:BackButton()] performAction:grey_tap()]; @@ -119,7 +121,7 @@ [[EarlGrey selectElementWithMatcher:ForwardButton()] performAction:grey_tap()]; [self assertStatusText:@"replaceStateHashWithObject" - withURL:replaceStateHashWithObjectURL + withOmniboxText:replaceStateHashWithObjectURL.GetContent() pageLoaded:YES]; // Push URL then replace it. Do this twice. @@ -127,44 +129,44 @@ web::test::HttpServer::MakeUrl(kPushStateHashStringURL); [ChromeEarlGrey tapWebViewElementWithID:@"pushStateHashString"]; [self assertStatusText:@"pushStateHashString" - withURL:pushStateHashStringURL + withOmniboxText:pushStateHashStringURL.GetContent() pageLoaded:NO]; const GURL replaceStateHashStringURL = web::test::HttpServer::MakeUrl(kReplaceStateHashStringURL); [ChromeEarlGrey tapWebViewElementWithID:@"replaceStateHashString"]; [self assertStatusText:@"replaceStateHashString" - withURL:replaceStateHashStringURL + withOmniboxText:replaceStateHashStringURL.GetContent() pageLoaded:NO]; const GURL pushStatePathURL = web::test::HttpServer::MakeUrl(kPushStatePathURL); [ChromeEarlGrey tapWebViewElementWithID:@"pushStatePath"]; [self assertStatusText:@"pushStatePath" - withURL:pushStatePathURL + withOmniboxText:pushStatePathURL.GetContent() pageLoaded:NO]; const GURL replaceStateRootPathSpaceURL = web::test::HttpServer::MakeUrl(kReplaceStateRootPathSpaceURL); [ChromeEarlGrey tapWebViewElementWithID:@"replaceStateRootPathSpace"]; [self assertStatusText:@"replaceStateRootPathSpace" - withURL:replaceStateRootPathSpaceURL + withOmniboxText:replaceStateRootPathSpaceURL.GetContent() pageLoaded:NO]; // Go back and check URLs. [[EarlGrey selectElementWithMatcher:BackButton()] performAction:grey_tap()]; [self assertStatusText:@"replaceStateHashString" - withURL:replaceStateHashStringURL + withOmniboxText:replaceStateHashStringURL.GetContent() pageLoaded:NO]; [[EarlGrey selectElementWithMatcher:BackButton()] performAction:grey_tap()]; [self assertStatusText:@"replaceStateHashWithObject" - withURL:replaceStateHashWithObjectURL + withOmniboxText:replaceStateHashWithObjectURL.GetContent() pageLoaded:NO]; // Go forward and check URL. [ChromeEarlGrey tapWebViewElementWithID:@"goForward2"]; [self assertStatusText:@"replaceStateRootPathSpace" - withURL:replaceStateRootPathSpaceURL + withOmniboxText:replaceStateRootPathSpaceURL.GetContent() pageLoaded:NO]; } @@ -180,11 +182,11 @@ web::test::HttpServer::MakeUrl(kPushStateHashStringURL); [ChromeEarlGrey tapWebViewElementWithID:@"pushStateHashString"]; [self assertStatusText:@"pushStateHashString" - withURL:pushStateHashStringURL + withOmniboxText:pushStateHashStringURL.GetContent() pageLoaded:NO]; [ChromeEarlGrey tapWebViewElementWithID:@"pushStateHashString"]; [self assertStatusText:@"pushStateHashString" - withURL:pushStateHashStringURL + withOmniboxText:pushStateHashStringURL.GetContent() pageLoaded:NO]; // Load a non-pushed URL. @@ -194,7 +196,7 @@ [ChromeEarlGrey loadURL:historyTestURL]; [ChromeEarlGrey tapWebViewElementWithID:@"pushStateHashString"]; [self assertStatusText:@"pushStateHashString" - withURL:pushStateHashStringURL + withOmniboxText:pushStateHashStringURL.GetContent() pageLoaded:NO]; // At this point the history looks like this: @@ -202,38 +204,54 @@ // Go back (to second history.html) and verify page did not load. [[EarlGrey selectElementWithMatcher:BackButton()] performAction:grey_tap()]; - [self assertStatusText:nil withURL:historyTestURL pageLoaded:NO]; + [self assertStatusText:nil + withOmniboxText:historyTestURL.GetContent() + pageLoaded:NO]; // Go back twice (to second #string) and verify page did load. [[EarlGrey selectElementWithMatcher:BackButton()] performAction:grey_tap()]; [[EarlGrey selectElementWithMatcher:BackButton()] performAction:grey_tap()]; - [self assertStatusText:nil withURL:pushStateHashStringURL pageLoaded:YES]; + [self assertStatusText:nil + withOmniboxText:pushStateHashStringURL.GetContent() + pageLoaded:YES]; // Go back once (to first #string) and verify page did not load. [[EarlGrey selectElementWithMatcher:BackButton()] performAction:grey_tap()]; [self assertStatusText:@"pushStateHashString" - withURL:pushStateHashStringURL + withOmniboxText:pushStateHashStringURL.GetContent() pageLoaded:NO]; // Go forward 4 entries at once (to third #string) and verify page did load. [ChromeEarlGrey tapWebViewElementWithID:@"goForward4"]; - [self assertStatusText:nil withURL:pushStateHashStringURL pageLoaded:YES]; + [self assertStatusText:nil + withOmniboxText:pushStateHashStringURL.GetContent() + pageLoaded:YES]; // Go back 4 entries at once (to first #string) and verify page did load. [ChromeEarlGrey tapWebViewElementWithID:@"goBack4"]; - [self assertStatusText:NULL withURL:pushStateHashStringURL pageLoaded:YES]; + [self assertStatusText:nil + withOmniboxText:pushStateHashStringURL.GetContent() + pageLoaded:YES]; } // Tests calling pushState with unicode characters. - (void)testHtml5HistoryPushUnicodeCharacters { - const GURL pushStateUnicodeURLEncoded = web::test::HttpServer::MakeUrl( - "http://ios/testing/data/http_server_files/" - "history.html#unicode%E1%84%91"); - const GURL pushStateUnicode2URLEncoded = web::test::HttpServer::MakeUrl( - "http://ios/testing/data/http_server_files/" - "history.html#unicode2%E2%88%A2"); + // The GURL object %-escapes Unicode characters in the URL's fragment, + // but the omnibox decodes them back to Unicode for display. + std::string pushStateUnicode = + web::test::HttpServer::MakeUrl( + "http://ios/testing/data/http_server_files/" + "history.html#unicode") + .GetContent() + + "\xe1\x84\x91"; + std::string pushStateUnicode2 = + web::test::HttpServer::MakeUrl( + "http://ios/testing/data/http_server_files/" + "history.html#unicode2") + .GetContent() + + "\xe2\x88\xa2"; const char pushStateUnicodeLabel[] = "Action: pushStateUnicodeᄑ"; NSString* pushStateUnicodeStatus = @"pushStateUnicodeᄑ"; const char pushStateUnicode2Label[] = "Action: pushStateUnicode2∢"; @@ -242,21 +260,16 @@ web::test::SetUpFileBasedHttpServer(); [ChromeEarlGrey loadURL:web::test::HttpServer::MakeUrl(kHistoryTestUrl)]; - // TODO(crbug.com/643458): The fact that the URL shows %-escaped is due to - // NSURL escaping to make UIWebView/JS happy. See if it's possible to - // represent differently such that it displays unescaped. // Do 2 push states with unicode characters. [ChromeEarlGrey tapWebViewElementWithID:@"pushStateUnicode"]; [[EarlGrey - selectElementWithMatcher:chrome_test_util::OmniboxText( - pushStateUnicodeURLEncoded.GetContent())] + selectElementWithMatcher:chrome_test_util::OmniboxText(pushStateUnicode)] assertWithMatcher:grey_notNil()]; [ChromeEarlGrey waitForWebViewContainingText:pushStateUnicodeLabel]; [ChromeEarlGrey tapWebViewElementWithID:@"pushStateUnicode2"]; [[EarlGrey - selectElementWithMatcher:chrome_test_util::OmniboxText( - pushStateUnicode2URLEncoded.GetContent())] + selectElementWithMatcher:chrome_test_util::OmniboxText(pushStateUnicode2)] assertWithMatcher:grey_notNil()]; [ChromeEarlGrey waitForWebViewContainingText:pushStateUnicode2Label]; @@ -266,18 +279,18 @@ [ChromeEarlGrey tapWebViewElementWithID:@"pushStatePath"]; [self assertStatusText:@"pushStatePath" - withURL:pushStatePathURL + withOmniboxText:pushStatePathURL.GetContent() pageLoaded:NO]; // Go back and check the unicode in the URL and status. [[EarlGrey selectElementWithMatcher:BackButton()] performAction:grey_tap()]; [self assertStatusText:pushStateUnicode2Status - withURL:pushStateUnicode2URLEncoded + withOmniboxText:pushStateUnicode2 pageLoaded:NO]; [[EarlGrey selectElementWithMatcher:BackButton()] performAction:grey_tap()]; [self assertStatusText:pushStateUnicodeStatus - withURL:pushStateUnicodeURLEncoded + withOmniboxText:pushStateUnicode pageLoaded:NO]; } @@ -321,10 +334,11 @@ #pragma mark - Utility methods -// Assert that status text |status| is displayed in the webview, that "onloaded" -// text is displayed if pageLoaded is YES, and that the URL is as expected. +// Assert that status text |status|, if non-nil, is displayed in the webview, +// that the omnibox text is as expected, and that "onload" text is displayed if +// pageLoaded is YES. - (void)assertStatusText:(NSString*)status - withURL:(const GURL&)urlToVerify + withOmniboxText:(const std::string&)omniboxText pageLoaded:(BOOL)pageLoaded { if (pageLoaded) { [ChromeEarlGrey waitForWebViewContainingText:"onload"]; @@ -332,14 +346,14 @@ [ChromeEarlGrey waitForWebViewNotContainingText:"onload"]; } - if (status != NULL) { + if (status != nil) { NSString* statusLabel = [NSString stringWithFormat:@"Action: %@", status]; [ChromeEarlGrey waitForWebViewContainingText:base::SysNSStringToUTF8(statusLabel)]; } - [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxText( - urlToVerify.GetContent())] + [[EarlGrey + selectElementWithMatcher:chrome_test_util::OmniboxText(omniboxText)] assertWithMatcher:grey_notNil()]; }
diff --git a/ios/chrome/common/BUILD.gn b/ios/chrome/common/BUILD.gn index 6297153..ace1da6 100644 --- a/ios/chrome/common/BUILD.gn +++ b/ios/chrome/common/BUILD.gn
@@ -21,7 +21,6 @@ "//components/version_info", "//components/version_info:version_string", "//ios/chrome/common/app_group:main_app", - "//ios/chrome/common/physical_web", "//net", "//url", ]
diff --git a/ios/chrome/common/physical_web/BUILD.gn b/ios/chrome/common/physical_web/BUILD.gn deleted file mode 100644 index e2ae5bb6..0000000 --- a/ios/chrome/common/physical_web/BUILD.gn +++ /dev/null
@@ -1,31 +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. - -source_set("physical_web") { - configs += [ "//build/config/compiler:enable_arc" ] - sources = [ - "physical_web_device.h", - "physical_web_device.mm", - "physical_web_request.h", - "physical_web_request.mm", - "physical_web_scanner.h", - "physical_web_scanner.mm", - "physical_web_types.h", - "physical_web_types.mm", - ] - - deps = [ - "//base", - "//components/physical_web/data_source", - "//components/version_info", - "//device/bluetooth/uribeacon", - "//google_apis", - "//ios/web/public", - ] - - libs = [ - "CoreBluetooth.framework", - "Foundation.framework", - ] -}
diff --git a/ios/chrome/common/physical_web/DEPS b/ios/chrome/common/physical_web/DEPS deleted file mode 100644 index 894d7dc2..0000000 --- a/ios/chrome/common/physical_web/DEPS +++ /dev/null
@@ -1,7 +0,0 @@ -# This code is used by iOS application extension and should keep the list -# of dependencies as small as possible. This is also why the code uses -# NSURL, NSSession, ... instead of Chrome network stack. -include_rules = [ - "+device/bluetooth/uribeacon", - "+google_apis", -]
diff --git a/ios/chrome/common/physical_web/OWNERS b/ios/chrome/common/physical_web/OWNERS deleted file mode 100644 index 56360bb..0000000 --- a/ios/chrome/common/physical_web/OWNERS +++ /dev/null
@@ -1,4 +0,0 @@ -olivierrobin@chromium.org - -# TEAM: ios-directory-owners@chromium.org -# OS: iOS
diff --git a/ios/chrome/common/physical_web/physical_web_device.h b/ios/chrome/common/physical_web/physical_web_device.h deleted file mode 100644 index 14107866..0000000 --- a/ios/chrome/common/physical_web/physical_web_device.h +++ /dev/null
@@ -1,56 +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 IOS_CHROME_COMMON_PHYSICAL_WEB_PHYSICAL_WEB_DEVICE_H_ -#define IOS_CHROME_COMMON_PHYSICAL_WEB_PHYSICAL_WEB_DEVICE_H_ - -#import <Foundation/Foundation.h> - -@interface PhysicalWebDevice : NSObject - -// Initializes a physical web device. See below for the description of the -// properties. -- (instancetype)initWithURL:(NSURL*)url - requestURL:(NSURL*)requestURL - icon:(NSURL*)icon - title:(NSString*)title - description:(NSString*)description - transmitPower:(int)transmitPower - rssi:(int)rssi - rank:(double)rank - scanTimestamp:(NSDate*)scanTimestamp NS_DESIGNATED_INITIALIZER; - -- (instancetype)init NS_UNAVAILABLE; - -// |url| is the expanded URL. -@property(nonatomic, readonly, strong) NSURL* url; - -// |requestUrl| is the broadcast URL. -@property(nonatomic, readonly, strong) NSURL* requestURL; - -// |icon| is the URL of the favicon. -@property(nonatomic, readonly, strong) NSURL* icon; - -// |title| is the title of the webpage. -@property(nonatomic, readonly, strong) NSString* title; - -// |description| is a short text description of the webpage content. -@property(nonatomic, readonly, strong) NSString* description; - -// |transmitPower| is the UriBeacon Tx Power Level. -@property(nonatomic, readonly) int transmitPower; - -// |rssi| is the received signal strength indicator (RSSI) of the peripheral, in -// decibels. -@property(nonatomic, readonly) int rssi; - -// |rank| of the physical web device returned by the server. -@property(nonatomic, readonly) double rank; - -// |scanTimestamp| is the time the URL was most recently seen. -@property(nonatomic, strong) NSDate* scanTimestamp; - -@end - -#endif // IOS_CHROME_COMMON_PHYSICAL_WEB_PHYSICAL_WEB_DEVICE_H_
diff --git a/ios/chrome/common/physical_web/physical_web_device.mm b/ios/chrome/common/physical_web/physical_web_device.mm deleted file mode 100644 index 420c3e9..0000000 --- a/ios/chrome/common/physical_web/physical_web_device.mm +++ /dev/null
@@ -1,88 +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. - -#import "ios/chrome/common/physical_web/physical_web_device.h" - -#include "base/logging.h" -#include "base/mac/scoped_nsobject.h" -#include "ios/chrome/common/physical_web/physical_web_types.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@implementation PhysicalWebDevice { - base::scoped_nsobject<NSURL> url_; - base::scoped_nsobject<NSURL> requestURL_; - base::scoped_nsobject<NSURL> icon_; - base::scoped_nsobject<NSString> title_; - base::scoped_nsobject<NSString> description_; - int rssi_; - int transmitPower_; - double rank_; - base::scoped_nsobject<NSDate> scanTimestamp_; -} - -@synthesize rssi = rssi_; -@synthesize transmitPower = transmitPower_; -@synthesize rank = rank_; - -- (instancetype)initWithURL:(NSURL*)url - requestURL:(NSURL*)requestURL - icon:(NSURL*)icon - title:(NSString*)title - description:(NSString*)description - transmitPower:(int)transmitPower - rssi:(int)rssi - rank:(double)rank - scanTimestamp:(NSDate*)scanTimestamp { - self = [super init]; - if (self) { - url_.reset(url); - requestURL_.reset(requestURL); - icon_.reset(icon); - title_.reset([title copy]); - description_.reset([description copy]); - transmitPower_ = transmitPower; - rssi_ = rssi; - rank_ = rank > physical_web::kMaxRank ? physical_web::kMaxRank : rank; - scanTimestamp_.reset(scanTimestamp); - } - return self; -} - -- (instancetype)init { - NOTREACHED(); - return nil; -} - -- (NSURL*)url { - return url_; -} - -- (NSURL*)requestURL { - return requestURL_; -} - -- (NSURL*)icon { - return icon_; -} - -- (NSString*)title { - return title_; -} - -- (NSString*)description { - return description_; -} - -- (NSDate*)scanTimestamp { - return scanTimestamp_; -} - -- (void)setScanTimestamp:(NSDate*)value { - scanTimestamp_.reset(value); -} - -@end
diff --git a/ios/chrome/common/physical_web/physical_web_request.h b/ios/chrome/common/physical_web/physical_web_request.h deleted file mode 100644 index 4187012..0000000 --- a/ios/chrome/common/physical_web/physical_web_request.h +++ /dev/null
@@ -1,39 +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 IOS_CHROME_COMMON_PHYSICAL_WEB_PHYSICAL_WEB_REQUEST_H_ -#define IOS_CHROME_COMMON_PHYSICAL_WEB_PHYSICAL_WEB_REQUEST_H_ - -#import <Foundation/Foundation.h> - -#import "ios/chrome/common/physical_web/physical_web_types.h" - -// This class will perform a metadata service web request to expand the given -// URL and return the metadata of the web page such as the title. - -@interface PhysicalWebRequest : NSObject - -// Initializes a metadata service web request with information about the -// physical web device. -- (instancetype)initWithDevice:(PhysicalWebDevice*)device - NS_DESIGNATED_INITIALIZER; - -- (instancetype)init NS_UNAVAILABLE; - -// Returns the URL sent in the query to the Physical Web service. -- (NSURL*)requestURL; - -// Starts the request and call the given |block| when finished. -// |block| should not be nil. -// If an error occurred, the block will be called with a non-nil error. -// When no error occurred, the result will be available in a PhysicalWebDevice -// data structure. -- (void)start:(physical_web::RequestFinishedBlock)block; - -// Cancels the request. -- (void)cancel; - -@end - -#endif // IOS_CHROME_COMMON_PHYSICAL_WEB_PHYSICAL_WEB_REQUEST_H_
diff --git a/ios/chrome/common/physical_web/physical_web_request.mm b/ios/chrome/common/physical_web/physical_web_request.mm deleted file mode 100644 index 4ddaae0..0000000 --- a/ios/chrome/common/physical_web/physical_web_request.mm +++ /dev/null
@@ -1,262 +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. - -#import "ios/chrome/common/physical_web/physical_web_request.h" - -#include "base/logging.h" -#include "base/mac/foundation_util.h" -#include "base/mac/scoped_block.h" -#include "base/mac/scoped_nsobject.h" -#include "base/metrics/histogram_macros.h" -#include "base/strings/sys_string_conversions.h" -#include "components/version_info/version_info.h" -#include "google_apis/google_api_keys.h" -#import "ios/chrome/common/physical_web/physical_web_device.h" -#import "ios/chrome/common/physical_web/physical_web_types.h" -#include "ios/web/public/user_agent.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -typedef void (^SessionCompletionProceduralBlock)(NSData* data, - NSURLResponse* response, - NSError* error); - -namespace { - -NSString* const kUrlsKey = @"urls"; -NSString* const kUrlKey = @"url"; -NSString* const kResultsKey = @"results"; -NSString* const kPageInfoKey = @"pageInfo"; -NSString* const kIconKey = @"icon"; -NSString* const kTitleKey = @"title"; -NSString* const kDescriptionKey = @"description"; -NSString* const kScannedUrlKey = @"scannedUrl"; -NSString* const kResolvedUrlKey = @"resolvedUrl"; - -NSString* const kMetadataServiceUrl = - @"https://physicalweb.googleapis.com/v1alpha1/urls:resolve"; -NSString* const kKeyQueryItemName = @"key"; -NSString* const kHTTPPOSTRequestMethod = @"POST"; - -std::string GetUserAgent() { - static std::string user_agent; - static dispatch_once_t once_token; - dispatch_once(&once_token, ^{ - std::string product("CriOS/"); - product += version_info::GetVersionNumber(); - user_agent = web::BuildUserAgentFromProduct(product); - }); - return user_agent; -} - -} // namespace - -@implementation PhysicalWebRequest { - base::mac::ScopedBlock<physical_web::RequestFinishedBlock> block_; - base::scoped_nsobject<PhysicalWebDevice> device_; - base::scoped_nsobject<NSMutableURLRequest> request_; - base::scoped_nsobject<NSURLSessionDataTask> urlSessionTask_; - base::scoped_nsobject<NSMutableData> data_; - base::scoped_nsobject<NSDate> startDate_; -} - -- (instancetype)initWithDevice:(PhysicalWebDevice*)device { - self = [super init]; - if (self) { - device_.reset(device); - } - return self; -} - -- (instancetype)init { - NOTREACHED(); - return nil; -} - -- (NSURL*)requestURL { - return [device_ requestURL]; -} - -- (void)cancel { - [urlSessionTask_ cancel]; - block_.reset(); -} - -- (void)start:(physical_web::RequestFinishedBlock)block { - block_.reset([block copy]); - data_.reset([[NSMutableData alloc] init]); - - // Creates the HTTP post request. - base::scoped_nsobject<NSURLComponents> components( - [[NSURLComponents alloc] initWithString:kMetadataServiceUrl]); - NSString* apiKey = - [NSString stringWithUTF8String:google_apis::GetAPIKey().c_str()]; - [components - setQueryItems:@[ [NSURLQueryItem queryItemWithName:kKeyQueryItemName - value:apiKey] ]]; - NSURL* url = [components URL]; - request_.reset([NSMutableURLRequest requestWithURL:url]); - [request_ setHTTPMethod:kHTTPPOSTRequestMethod]; - - // body of the POST request. - NSDictionary* jsonBody = - @{ kUrlsKey : @[ @{kUrlKey : [[device_ requestURL] absoluteString]} ] }; - [request_ setHTTPBody:[NSJSONSerialization dataWithJSONObject:jsonBody - options:0 - error:NULL]]; - [request_ setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; - [request_ setValue:base::SysUTF8ToNSString(GetUserAgent()) - forHTTPHeaderField:@"User-Agent"]; - - // Set the Accept-Language header from the locale language code. This may - // cause us to fetch metadata for the wrong region in languages such as - // Chinese that vary significantly between regions. - // TODO(mattreynolds): Use the same Accept-Language string as WKWebView. - NSString* acceptLanguage = - [[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]; - [request_ setValue:acceptLanguage forHTTPHeaderField:@"Acccept-Language"]; - - startDate_.reset([NSDate date]); - // Starts the request. - NSURLSessionConfiguration* sessionConfiguration = - [NSURLSessionConfiguration ephemeralSessionConfiguration]; - sessionConfiguration.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicyNever; - NSURLSession* session = - [NSURLSession sessionWithConfiguration:sessionConfiguration - delegate:nil - delegateQueue:[NSOperationQueue mainQueue]]; - __weak PhysicalWebRequest* weakSelf = self; - SessionCompletionProceduralBlock completionHandler = - ^(NSData* data, NSURLResponse* response, NSError* error) { - base::scoped_nsobject<PhysicalWebRequest> strongSelf(weakSelf); - if (!strongSelf) { - return; - } - if (error) { - [strongSelf callBlockWithError:error jsonObject:nil]; - } else { - [strongSelf.get()->data_ appendData:data]; - [strongSelf sessionDidFinishLoading]; - } - }; - urlSessionTask_.reset([session dataTaskWithRequest:request_ - completionHandler:completionHandler]); - [urlSessionTask_ resume]; -} - -- (void)sessionDidFinishLoading { - NSError* error = nil; - NSDictionary* jsonObject = - [NSJSONSerialization JSONObjectWithData:data_ options:0 error:&error]; - if (error != nil) { - [self callBlockWithError:error jsonObject:nil]; - return; - } - if (![self isValidJSON:jsonObject]) { - [self callBlockWithError: - [NSError errorWithDomain:physical_web::kPhysicalWebErrorDomain - code:physical_web::ERROR_INVALID_JSON - userInfo:nil] - jsonObject:jsonObject]; - return; - } - [self callBlockWithError:error jsonObject:jsonObject]; -} - -// Checks whether the JSON object has the correct format. -// The format should be similar to the following: -// { -// "results":[ -// { -// "pageInfo":{ -// "title":"Google" -// "description":"Search the world's information" -// "icon":"https://www.google.com/favicon.ico" -// } -// "scannedUrl":"https://www.google.com" -// "resolvedUrl":"https://www.google.com" -// } -// ] -// } -- (BOOL)isValidJSON:(id)jsonObject { - NSDictionary* dict = base::mac::ObjCCast<NSDictionary>(jsonObject); - if (!dict) { - return NO; - } - NSArray* list = base::mac::ObjCCast<NSArray>(dict[kResultsKey]); - if (!list) { - return NO; - } - if ([list count] != 1) { - return NO; - } - NSDictionary* item = base::mac::ObjCCast<NSDictionary>(list[0]); - if (!item) { - return NO; - } - return YES; -} - -// Calls the block passed as parameter of -start: when the request is finished. -- (void)callBlockWithError:(NSError*)error - jsonObject:(NSDictionary*)jsonObject { - if (error) { - if (block_.get()) { - block_.get()(nil, error); - } - } else { - NSTimeInterval roundTripTime = - [[NSDate date] timeIntervalSinceDate:startDate_]; - int roundTripTimeMS = 1000 * roundTripTime; - UMA_HISTOGRAM_COUNTS("PhysicalWeb.RoundTripTimeMilliseconds", - roundTripTimeMS); - NSArray* list = jsonObject[kResultsKey]; - NSDictionary* item = list[0]; - - NSDictionary* pageInfo = - base::mac::ObjCCast<NSDictionary>(item[kPageInfoKey]); - NSString* scannedUrlString = - base::mac::ObjCCast<NSString>(item[kScannedUrlKey]); - NSString* resolvedUrlString = - base::mac::ObjCCast<NSString>(item[kResolvedUrlKey]); - - // Verify required fields pageInfo, scannedUrl, and resolvedUrl are present. - if (pageInfo == nil || scannedUrlString == nil || - resolvedUrlString == nil) { - error = [NSError errorWithDomain:physical_web::kPhysicalWebErrorDomain - code:physical_web::ERROR_INVALID_JSON - userInfo:nil]; - if (block_.get()) { - block_.get()(nil, error); - } - return; - } - - // Read optional fields. - NSString* iconString = base::mac::ObjCCast<NSString>(pageInfo[kIconKey]); - NSString* description = - base::mac::ObjCCast<NSString>(pageInfo[kDescriptionKey]); - NSString* title = base::mac::ObjCCast<NSString>(pageInfo[kTitleKey]); - NSURL* resolvedUrl = - resolvedUrlString ? [NSURL URLWithString:resolvedUrlString] : nil; - NSURL* icon = iconString ? [NSURL URLWithString:iconString] : nil; - base::scoped_nsobject<PhysicalWebDevice> device([[PhysicalWebDevice alloc] - initWithURL:resolvedUrl - requestURL:[device_ requestURL] - icon:icon - title:title - description:description - transmitPower:[device_ transmitPower] - rssi:[device_ rssi] - rank:physical_web::kMaxRank - scanTimestamp:[device_ scanTimestamp]]); - if (block_.get() != nil) { - block_.get()(device, nil); - } - } -} - -@end
diff --git a/ios/chrome/common/physical_web/physical_web_scanner.h b/ios/chrome/common/physical_web/physical_web_scanner.h deleted file mode 100644 index 5cb2d45..0000000 --- a/ios/chrome/common/physical_web/physical_web_scanner.h +++ /dev/null
@@ -1,75 +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 IOS_CHROME_COMMON_PHYSICAL_WEB_PHYSICAL_WEB_SCANNER_H_ -#define IOS_CHROME_COMMON_PHYSICAL_WEB_PHYSICAL_WEB_SCANNER_H_ - -#import <Foundation/Foundation.h> - -#include <memory> -#include <vector> - -namespace physical_web { -struct Metadata; -using MetadataList = std::vector<Metadata>; -} - -@protocol PhysicalWebScannerDelegate; - -// This class will scan for physical web devices. - -@interface PhysicalWebScanner : NSObject - -// When onLostDetectionEnabled is YES, the delegate will be notified if a URL -// that was previously nearby is no longer detected. Changing this value while -// scanning is active will reset the list of nearby URLs. -@property(nonatomic, assign) BOOL onLostDetectionEnabled; - -// When networkRequest is NO, no network request will be sent. -@property(nonatomic, assign) BOOL networkRequestEnabled; - -// When networkRequest is NO, it returns the number of discovered beacons. -@property(nonatomic, readonly) int unresolvedBeaconsCount; - -// Whether bluetooth is enabled. Must not be read before the first call of -// scannerBluetoothStatusUpdated. -@property(nonatomic, readonly) BOOL bluetoothEnabled; - -// Initializes a physical web device scanner. -- (instancetype)initWithDelegate:(id<PhysicalWebScannerDelegate>)delegate - NS_DESIGNATED_INITIALIZER; - -- (instancetype)init NS_UNAVAILABLE; - -// Start scanning and clear the list of discovered devices. The scanning might -// not start effectively immediately. -// It can happen when the bluetooth is turned off. In this case, scanning will -// start as soon as the bluetooth is turned on. -- (void)start; - -// Stop scanning. -- (void)stop; - -// Returns a list of physical web devices (PhysicalWebDevice). -- (NSArray*)devices; - -// Returns the metadata for all resolved physical web URLs. The returned value -// will never be null; if no metadata has been received then an empty list is -// returned. -- (std::unique_ptr<physical_web::MetadataList>)metadataList; - -@end - -@protocol PhysicalWebScannerDelegate<NSObject> - -// This delegate method is called when the list of discovered devices is updated -// by the scanner. -- (void)scannerUpdatedDevices:(PhysicalWebScanner*)scanner; - -// This delegate method is called when the bluetooth status is updated. -- (void)scannerBluetoothStatusUpdated:(PhysicalWebScanner*)scanner; - -@end - -#endif // IOS_CHROME_COMMON_PHYSICAL_WEB_PHYSICAL_WEB_SCANNER_H_
diff --git a/ios/chrome/common/physical_web/physical_web_scanner.mm b/ios/chrome/common/physical_web/physical_web_scanner.mm deleted file mode 100644 index 04fbd328..0000000 --- a/ios/chrome/common/physical_web/physical_web_scanner.mm +++ /dev/null
@@ -1,504 +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. - -#import "ios/chrome/common/physical_web/physical_web_scanner.h" - -#import <CoreBluetooth/CoreBluetooth.h> - -#include <string> -#include <vector> - -#include "base/logging.h" -#import "base/mac/scoped_nsobject.h" -#include "base/memory/ptr_util.h" -#include "base/strings/sys_string_conversions.h" -#include "components/physical_web/data_source/physical_web_data_source.h" -#include "device/bluetooth/uribeacon/uri_encoder.h" -#import "ios/chrome/common/physical_web/physical_web_device.h" -#import "ios/chrome/common/physical_web/physical_web_request.h" -#import "ios/chrome/common/physical_web/physical_web_types.h" -#include "url/gurl.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { - -NSString* const kUriBeaconServiceUUID = @"FED8"; -NSString* const kEddystoneBeaconServiceUUID = @"FEAA"; - -// The length of time in seconds since a URL was last seen before it should be -// considered lost (ie, no longer nearby). -const NSTimeInterval kLostThresholdSeconds = 15.0; -// The time interval in seconds between checks for lost URLs. -const NSTimeInterval kUpdateIntervalSeconds = 6.0; - -enum BeaconType { - BEACON_TYPE_NONE, - BEACON_TYPE_URIBEACON, - BEACON_TYPE_EDDYSTONE, -}; - -} // namespace - -@interface PhysicalWebScanner ()<CBCentralManagerDelegate> - -// Decodes the UriBeacon information in the given |data| and a beacon |type| to -// return an unresolved PhysicalWebDevice instance. It also stores the given -// |rssi| in the result. -+ (PhysicalWebDevice*)newDeviceFromData:(NSData*)data - rssi:(int)rssi - type:(BeaconType)type; -// Starts the CoreBluetooth scanner when the bluetooth is powered on and starts -// the update timer. -- (void)reallyStart; -// Stops the CoreBluetooth scanner and update timer. -- (void)reallyStop; -// Timer callback to check for lost URLs based on the elapsed time since they -// were last seen. -- (void)onUpdateTimeElapsed:(NSTimer*)timer; -// Requests metadata of a device if the same URL has not been requested before. -- (void)requestMetadataForDevice:(PhysicalWebDevice*)device; -// Returns the beacon type given the advertisement data. -+ (BeaconType)beaconTypeForAdvertisementData:(NSDictionary*)advertisementData; - -@end - -@implementation PhysicalWebScanner { - // Delegate that will be notified when the list of devices change. - __weak id<PhysicalWebScannerDelegate> delegate_; - // The value of |started_| is YES when the scanner has been started and NO - // when it's been stopped. The initial value is NO. - BOOL started_; - // The value is valid when the scanner has been started. If bluetooth is not - // powered on, the value is YES, if it's powered on and the CoreBluetooth - // scanner has started, the value is NO. - BOOL pendingStart_; - // List of PhysicalWebRequest that we're waiting the response from. - base::scoped_nsobject<NSMutableArray> pendingRequests_; - // List of resolved PhysicalWebDevice. - base::scoped_nsobject<NSMutableArray> devices_; - // List of URLs that have been resolved or have a pending resolution from a - // PhysicalWebRequest. - base::scoped_nsobject<NSMutableSet> devicesUrls_; - // List of final URLs that have been resolved. This set will help us - // deduplicate the final URLs. - base::scoped_nsobject<NSMutableSet> finalUrls_; - // CoreBluetooth scanner. - base::scoped_nsobject<CBCentralManager> centralManager_; - // When YES, we will notify the delegate if a previously nearby URL is lost - // and remove it from the list of nearby devices. - BOOL onLostDetectionEnabled_; - // The value is YES if network requests can be sent. - BOOL networkRequestEnabled_; - // List of unresolved PhysicalWebDevice when network requests are not enabled. - base::scoped_nsobject<NSMutableArray> unresolvedDevices_; - // A repeating timer to check for lost URLs. If the elapsed time since an URL - // was last seen exceeds a threshold, the URL is considered lost. - base::scoped_nsobject<NSTimer> updateTimer_; -} - -@synthesize onLostDetectionEnabled = onLostDetectionEnabled_; -@synthesize networkRequestEnabled = networkRequestEnabled_; - -- (instancetype)initWithDelegate:(id<PhysicalWebScannerDelegate>)delegate { - self = [super init]; - if (self) { - delegate_ = delegate; - devices_.reset([[NSMutableArray alloc] init]); - devicesUrls_.reset([[NSMutableSet alloc] init]); - finalUrls_.reset([[NSMutableSet alloc] init]); - pendingRequests_.reset([[NSMutableArray alloc] init]); - centralManager_.reset([[CBCentralManager alloc] - initWithDelegate:self - queue:dispatch_get_main_queue() - options:@{ - CBCentralManagerOptionShowPowerAlertKey : @NO - }]); - unresolvedDevices_.reset([[NSMutableArray alloc] init]); - } - return self; -} - -- (instancetype)init { - NOTREACHED(); - return nil; -} - -- (void)dealloc { - [centralManager_ setDelegate:nil]; - centralManager_.reset(); - if (updateTimer_.get()) { - [updateTimer_ invalidate]; - updateTimer_.reset(); - } -} - -- (void)start { - [self stop]; - [finalUrls_ removeAllObjects]; - [devicesUrls_ removeAllObjects]; - [devices_ removeAllObjects]; - started_ = YES; - if ([self bluetoothEnabled]) - [self reallyStart]; - else - pendingStart_ = YES; -} - -- (void)stop { - if (!started_) - return; - for (PhysicalWebRequest* request in pendingRequests_.get()) { - [request cancel]; - } - [pendingRequests_ removeAllObjects]; - if (!pendingStart_ && [self bluetoothEnabled]) { - [self reallyStop]; - } - pendingStart_ = NO; - started_ = NO; - if (onLostDetectionEnabled_ && [devices_ count]) { - [delegate_ scannerUpdatedDevices:self]; - } -} - -- (NSArray*)devices { - if (![self bluetoothEnabled]) { - return [NSArray array]; - } - return [devices_ sortedArrayUsingComparator:^(id obj1, id obj2) { - PhysicalWebDevice* device1 = obj1; - PhysicalWebDevice* device2 = obj2; - // Sorts in ascending order. - if ([device1 rank] > [device2 rank]) { - return NSOrderedDescending; - } - if ([device1 rank] < [device2 rank]) { - return NSOrderedAscending; - } - return NSOrderedSame; - }]; -} - -- (std::unique_ptr<physical_web::MetadataList>)metadataList { - auto metadataRet = base::MakeUnique<physical_web::MetadataList>(); - - for (PhysicalWebDevice* device in [self devices]) { - std::string scannedUrl = - base::SysNSStringToUTF8([[device requestURL] absoluteString]); - std::string resolvedUrl = - base::SysNSStringToUTF8([[device url] absoluteString]); - std::string icon = base::SysNSStringToUTF8([[device icon] absoluteString]); - std::string title = base::SysNSStringToUTF8([device title]); - std::string description = base::SysNSStringToUTF8([device description]); - - metadataRet->emplace_back(); - physical_web::Metadata& metadataItem = metadataRet->back(); - metadataItem.scanned_url = GURL(scannedUrl); - metadataItem.resolved_url = GURL(resolvedUrl); - metadataItem.icon_url = GURL(icon); - metadataItem.title = title; - metadataItem.description = description; - } - - return metadataRet; -} - -- (void)setNetworkRequestEnabled:(BOOL)enabled { - if (networkRequestEnabled_ == enabled) { - return; - } - networkRequestEnabled_ = enabled; - if (!networkRequestEnabled_) - return; - - // Sends the pending requests. - for (PhysicalWebDevice* device in unresolvedDevices_.get()) { - [self requestMetadataForDevice:device]; - } - [unresolvedDevices_ removeAllObjects]; -} - -- (void)setOnLostDetectionEnabled:(BOOL)enabled { - if (enabled == onLostDetectionEnabled_) { - return; - } - onLostDetectionEnabled_ = enabled; - if (started_) { - [self start]; - } -} - -- (int)unresolvedBeaconsCount { - return [unresolvedDevices_ count]; -} - -- (BOOL)bluetoothEnabled { - BOOL bluetoothEnabled = NO; - if (@available(iOS 10, *)) { - bluetoothEnabled = [centralManager_ state] == CBManagerStatePoweredOn; - } -#if !defined(__IPHONE_10_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0 - else { - bluetoothEnabled = (CBCentralManagerState)[centralManager_ state] == - CBCentralManagerStatePoweredOn; - } -#endif - return bluetoothEnabled; -} - -- (void)reallyStart { - pendingStart_ = NO; - - if (updateTimer_.get()) { - [updateTimer_ invalidate]; - updateTimer_.reset(); - } - - NSArray* serviceUUIDs = @[ - [CBUUID UUIDWithString:kUriBeaconServiceUUID], - [CBUUID UUIDWithString:kEddystoneBeaconServiceUUID] - ]; - if (onLostDetectionEnabled_) { - // Register a repeating timer to periodically check for lost URLs. - updateTimer_.reset([NSTimer - scheduledTimerWithTimeInterval:kUpdateIntervalSeconds - target:self - selector:@selector(onUpdateTimeElapsed:) - userInfo:nil - repeats:YES]); - } - [centralManager_ scanForPeripheralsWithServices:serviceUUIDs options:nil]; -} - -- (void)reallyStop { - [centralManager_ stopScan]; -} - -- (void)onUpdateTimeElapsed:(NSTimer*)timer { - NSDate* now = [NSDate date]; - NSMutableArray* lostDevices = [NSMutableArray array]; - NSMutableArray* lostUnresolvedDevices = [NSMutableArray array]; - NSMutableArray* lostScannedUrls = [NSMutableArray array]; - - for (PhysicalWebDevice* device in devices_.get()) { - NSDate* scanTimestamp = [device scanTimestamp]; - NSTimeInterval elapsedSeconds = [now timeIntervalSinceDate:scanTimestamp]; - if (elapsedSeconds > kLostThresholdSeconds) { - [lostDevices addObject:device]; - [lostScannedUrls addObject:[device requestURL]]; - [devicesUrls_ removeObject:[device requestURL]]; - [finalUrls_ removeObject:[device url]]; - } - } - - for (PhysicalWebDevice* device in unresolvedDevices_.get()) { - NSDate* scanTimestamp = [device scanTimestamp]; - NSTimeInterval elapsedSeconds = [now timeIntervalSinceDate:scanTimestamp]; - if (elapsedSeconds > kLostThresholdSeconds) { - [lostUnresolvedDevices addObject:device]; - [lostScannedUrls addObject:[device requestURL]]; - [devicesUrls_ removeObject:[device requestURL]]; - } - } - - NSMutableArray* requestsToRemove = [NSMutableArray array]; - for (PhysicalWebRequest* request in pendingRequests_.get()) { - if ([lostScannedUrls containsObject:[request requestURL]]) { - [request cancel]; - [requestsToRemove addObject:request]; - } - } - - [devices_ removeObjectsInArray:lostDevices]; - [unresolvedDevices_ removeObjectsInArray:lostUnresolvedDevices]; - [pendingRequests_ removeObjectsInArray:requestsToRemove]; - - if ([lostDevices count]) { - [delegate_ scannerUpdatedDevices:self]; - } - - // TODO(crbug.com/657056): Remove this workaround when radar is fixed. - // For unknown reasons, when scanning for longer periods (on the order of - // minutes), the scanner is less reliable at detecting all nearby URLs. As a - // workaround, we restart the scanner each time we check for lost URLs. - if (!pendingStart_) { - NSArray* serviceUUIDs = @[ - [CBUUID UUIDWithString:kUriBeaconServiceUUID], - [CBUUID UUIDWithString:kEddystoneBeaconServiceUUID] - ]; - [centralManager_ stopScan]; - [centralManager_ scanForPeripheralsWithServices:serviceUUIDs options:nil]; - } - - if (updateTimer_.get() && pendingStart_ && [devices_ count] == 0) { - [updateTimer_ invalidate]; - updateTimer_.reset(); - } -} - -#pragma mark - -#pragma mark CBCentralManagerDelegate methods - -- (void)centralManagerDidUpdateState:(CBCentralManager*)central { - if ([self bluetoothEnabled]) { - if (pendingStart_) - [self reallyStart]; - } else { - if (started_ && !pendingStart_) { - pendingStart_ = YES; - } - } - [delegate_ scannerBluetoothStatusUpdated:self]; -} - -+ (BeaconType)beaconTypeForAdvertisementData:(NSDictionary*)advertisementData { - NSDictionary* serviceData = - [advertisementData objectForKey:CBAdvertisementDataServiceDataKey]; - if ([serviceData objectForKey:[CBUUID UUIDWithString:kUriBeaconServiceUUID]]) - return BEACON_TYPE_URIBEACON; - if ([serviceData - objectForKey:[CBUUID UUIDWithString:kEddystoneBeaconServiceUUID]]) - return BEACON_TYPE_EDDYSTONE; - return BEACON_TYPE_NONE; -} - -- (void)centralManager:(CBCentralManager*)central - didDiscoverPeripheral:(CBPeripheral*)peripheral - advertisementData:(NSDictionary*)advertisementData - RSSI:(NSNumber*)RSSI { - BeaconType type = - [PhysicalWebScanner beaconTypeForAdvertisementData:advertisementData]; - if (type == BEACON_TYPE_NONE) - return; - - NSDictionary* serviceData = - [advertisementData objectForKey:CBAdvertisementDataServiceDataKey]; - NSData* data = nil; - switch (type) { - case BEACON_TYPE_URIBEACON: - data = [serviceData - objectForKey:[CBUUID UUIDWithString:kUriBeaconServiceUUID]]; - break; - case BEACON_TYPE_EDDYSTONE: - data = [serviceData - objectForKey:[CBUUID UUIDWithString:kEddystoneBeaconServiceUUID]]; - break; - default: - // Do nothing. - break; - } - DCHECK(data); - - base::scoped_nsobject<PhysicalWebDevice> device([PhysicalWebScanner - newDeviceFromData:data - rssi:[RSSI intValue] - type:type]); - // Skip if the data couldn't be parsed. - if (!device.get()) - return; - - // If the URL has already been seen, update its timestamp. - if ([devicesUrls_ containsObject:[device requestURL]]) { - for (PhysicalWebDevice* unresolvedDevice in unresolvedDevices_.get()) { - if ([[unresolvedDevice requestURL] isEqual:[device requestURL]]) { - [unresolvedDevice setScanTimestamp:[NSDate date]]; - return; - } - } - for (PhysicalWebDevice* resolvedDevice in devices_.get()) { - if ([[resolvedDevice requestURL] isEqual:[device requestURL]]) { - [resolvedDevice setScanTimestamp:[NSDate date]]; - break; - } - } - return; - } - - [device setScanTimestamp:[NSDate date]]; - [devicesUrls_ addObject:[device requestURL]]; - - if (networkRequestEnabled_) { - [self requestMetadataForDevice:device]; - } else { - [unresolvedDevices_ addObject:device]; - [delegate_ scannerUpdatedDevices:self]; - } -} - -#pragma mark - -#pragma mark UriBeacon resolution - -+ (PhysicalWebDevice*)newDeviceFromData:(NSData*)data - rssi:(int)rssi - type:(BeaconType)type { - // No UriBeacon service data. - if (!data) - return nil; - // UriBeacon service data too small. - if ([data length] <= 2) - return nil; - - const uint8_t* bytes = static_cast<const uint8_t*>([data bytes]); - if (type == BEACON_TYPE_EDDYSTONE) { - // The packet type is encoded in the high-order 4 bits. - // Returns if it's not an Eddystone-URL. - if ((bytes[0] & 0xf0) != 0x10) - return nil; - } - - // - transmit power is at offset 1 - // TX Power in the UriBeacon advertising packet is the received power at 0 - // meters. The Transmit Power Level represents the transmit power level in - // dBm, and the value ranges from -100 dBm to +20 dBm to a resolution of 1 - // dBm. - int transmitPower = static_cast<char>(bytes[1]); - // - scheme and URL are at offset 2. - std::vector<uint8_t> encodedURI(&bytes[2], &bytes[[data length]]); - std::string utf8URI; - device::DecodeUriBeaconUri(encodedURI, utf8URI); - NSString* uriString = base::SysUTF8ToNSString(utf8URI); - NSURL* url = [NSURL URLWithString:uriString]; - - // Ensure URL is valid. - if (!url) - return nil; - - return [[PhysicalWebDevice alloc] initWithURL:url - requestURL:url - icon:nil - title:nil - description:nil - transmitPower:transmitPower - rssi:rssi - rank:physical_web::kMaxRank - scanTimestamp:[NSDate date]]; -} - -- (void)requestMetadataForDevice:(PhysicalWebDevice*)device { - base::scoped_nsobject<PhysicalWebRequest> request( - [[PhysicalWebRequest alloc] initWithDevice:device]); - PhysicalWebRequest* strongRequest = request.get(); - [pendingRequests_ addObject:strongRequest]; - __weak PhysicalWebScanner* weakSelf = self; - [request start:^(PhysicalWebDevice* device, NSError* error) { - base::scoped_nsobject<PhysicalWebScanner> strongSelf(weakSelf); - if (!strongSelf) { - return; - } - // ignore if there's an error. - if (!error) { - if (![strongSelf.get()->finalUrls_ containsObject:[device url]]) { - [strongSelf.get()->devices_ addObject:device]; - [strongSelf.get()->delegate_ scannerUpdatedDevices:weakSelf]; - [strongSelf.get()->finalUrls_ addObject:[device url]]; - } - } - [strongSelf.get()->pendingRequests_ removeObject:strongRequest]; - }]; -} - -@end
diff --git a/ios/chrome/common/physical_web/physical_web_types.h b/ios/chrome/common/physical_web/physical_web_types.h deleted file mode 100644 index f3fb67bd..0000000 --- a/ios/chrome/common/physical_web/physical_web_types.h +++ /dev/null
@@ -1,30 +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 IOS_CHROME_COMMON_PHYSICAL_WEB_PHYSICAL_WEB_TYPES_H_ -#define IOS_CHROME_COMMON_PHYSICAL_WEB_PHYSICAL_WEB_TYPES_H_ - -#import <Foundation/Foundation.h> - -@class PhysicalWebDevice; - -namespace physical_web { - -typedef void (^RequestFinishedBlock)(PhysicalWebDevice*, NSError*); - -// Error domain for physical web. -extern NSString* const kPhysicalWebErrorDomain; - -// Error codes for physical web errors. -enum PhysicalWebErrorCode { - // The JSON data returned by the metadata service is invalid. - ERROR_INVALID_JSON = 1, -}; - -// Maximum value for the rank of a physical web device. -extern const double kMaxRank; - -} // namespace physical_web - -#endif // IOS_CHROME_COMMON_PHYSICAL_WEB_PHYSICAL_WEB_TYPES_H_
diff --git a/ios/chrome/common/physical_web/physical_web_types.mm b/ios/chrome/common/physical_web/physical_web_types.mm deleted file mode 100644 index 5b47095..0000000 --- a/ios/chrome/common/physical_web/physical_web_types.mm +++ /dev/null
@@ -1,17 +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. - -#import "ios/chrome/common/physical_web/physical_web_types.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace physical_web { - -NSString* const kPhysicalWebErrorDomain = @"kPhysicalWebErrorDomain"; - -const double kMaxRank = 1000.0; - -} // namespace physical_web
diff --git a/ios/chrome/test/testing_application_context.h b/ios/chrome/test/testing_application_context.h index aae280d..79cf7cb 100644 --- a/ios/chrome/test/testing_application_context.h +++ b/ios/chrome/test/testing_application_context.h
@@ -51,7 +51,6 @@ gcm::GCMDriver* GetGCMDriver() override; component_updater::ComponentUpdateService* GetComponentUpdateService() override; - physical_web::PhysicalWebDataSource* GetPhysicalWebDataSource() override; private: base::ThreadChecker thread_checker_;
diff --git a/ios/chrome/test/testing_application_context.mm b/ios/chrome/test/testing_application_context.mm index e0e552a..4b316ef 100644 --- a/ios/chrome/test/testing_application_context.mm +++ b/ios/chrome/test/testing_application_context.mm
@@ -158,9 +158,3 @@ DCHECK(thread_checker_.CalledOnValidThread()); return nullptr; } - -physical_web::PhysicalWebDataSource* -TestingApplicationContext::GetPhysicalWebDataSource() { - DCHECK(thread_checker_.CalledOnValidThread()); - return nullptr; -}
diff --git a/ios/web/web_state/js/resources/form.js b/ios/web/web_state/js/resources/form.js index 38c2eb6c..c960799 100644 --- a/ios/web/web_state/js/resources/form.js +++ b/ios/web/web_state/js/resources/form.js
@@ -14,8 +14,8 @@ /** Beginning of anonymous object */ (function() { - // Skip iframes that have the same origin as the main frame. For such frames - // no form related actions (eg. filling, saving) are supported. + // Skip iframes that have different origins from the main frame. For such + // frames no form related actions (eg. filling, saving) are supported. try { // The following line generates exception for iframes that have different // origin that.
diff --git a/mash/catalog_viewer/catalog_viewer.cc b/mash/catalog_viewer/catalog_viewer.cc index 5a54a98c..3849e67 100644 --- a/mash/catalog_viewer/catalog_viewer.cc +++ b/mash/catalog_viewer/catalog_viewer.cc
@@ -53,7 +53,8 @@ SetBorder(views::CreateEmptyBorder(gfx::Insets(kPadding))); SetBackground(views::CreateStandardPanelBackground()); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); views::ColumnSet* columns = layout->AddColumnSet(0); columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0,
diff --git a/mash/example/window_type_launcher/window_type_launcher.cc b/mash/example/window_type_launcher/window_type_launcher.cc index 5189b0c..bcf0119 100644 --- a/mash/example/window_type_launcher/window_type_launcher.cc +++ b/mash/example/window_type_launcher/window_type_launcher.cc
@@ -275,7 +275,8 @@ MdTextButton::Create(this, base::ASCIIToUTF16("Jank for (s):"))), jank_duration_field_(new views::Textfield) { SetBorder(views::CreateEmptyBorder(gfx::Insets(5))); - views::GridLayout* layout = views::GridLayout::CreateAndInstall(this); + views::GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); views::ColumnSet* column_set = layout->AddColumnSet(0); column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc index aa5dd2dd..be4894c 100644 --- a/media/base/video_frame.cc +++ b/media/base/video_frame.cc
@@ -133,7 +133,6 @@ case PIXEL_FORMAT_YUV444P12: case PIXEL_FORMAT_YV12A: case PIXEL_FORMAT_UYVY: - case PIXEL_FORMAT_I422: return true; case PIXEL_FORMAT_UNKNOWN: break; @@ -168,7 +167,7 @@ return true; // Make sure new formats are properly accounted for in the method. - static_assert(PIXEL_FORMAT_MAX == 27, + static_assert(PIXEL_FORMAT_MAX == 26, "Added pixel format, please review IsValidConfig()"); if (format == PIXEL_FORMAT_UNKNOWN) { @@ -538,7 +537,6 @@ case PIXEL_FORMAT_YUV420P12: case PIXEL_FORMAT_YUV422P12: case PIXEL_FORMAT_YUV444P12: - case PIXEL_FORMAT_I422: return 3; case PIXEL_FORMAT_YV12A: return 4; @@ -852,7 +850,6 @@ case media::PIXEL_FORMAT_MJPEG: case media::PIXEL_FORMAT_MT21: case media::PIXEL_FORMAT_Y8: - case media::PIXEL_FORMAT_I422: bits_per_channel = 8; break; case media::PIXEL_FORMAT_YUV420P9: @@ -1109,7 +1106,6 @@ return gfx::Size(1, 1); case PIXEL_FORMAT_YV16: - case PIXEL_FORMAT_I422: case PIXEL_FORMAT_YUV422P9: case PIXEL_FORMAT_YUV422P10: case PIXEL_FORMAT_YUV422P12: @@ -1178,7 +1174,6 @@ case PIXEL_FORMAT_YV12A: case PIXEL_FORMAT_YV24: case PIXEL_FORMAT_Y8: - case PIXEL_FORMAT_I422: return 1; case PIXEL_FORMAT_MJPEG: return 0;
diff --git a/media/base/video_frame_unittest.cc b/media/base/video_frame_unittest.cc index 0ce3a44..0d7440e 100644 --- a/media/base/video_frame_unittest.cc +++ b/media/base/video_frame_unittest.cc
@@ -464,7 +464,6 @@ case PIXEL_FORMAT_UYVY: case PIXEL_FORMAT_YUY2: case PIXEL_FORMAT_YV16: - case PIXEL_FORMAT_I422: EXPECT_EQ(48u, allocation_size) << VideoPixelFormatToString(format); break; case PIXEL_FORMAT_YV12:
diff --git a/media/base/video_types.cc b/media/base/video_types.cc index 25fdbf5..0f2d540a 100644 --- a/media/base/video_types.cc +++ b/media/base/video_types.cc
@@ -64,8 +64,6 @@ return "PIXEL_FORMAT_Y8"; case PIXEL_FORMAT_Y16: return "PIXEL_FORMAT_Y16"; - case PIXEL_FORMAT_I422: - return "PIXEL_FORMAT_I422"; } NOTREACHED() << "Invalid VideoPixelFormat provided: " << format; return ""; @@ -90,7 +88,6 @@ case PIXEL_FORMAT_YUV420P12: case PIXEL_FORMAT_YUV422P12: case PIXEL_FORMAT_YUV444P12: - case PIXEL_FORMAT_I422: return true; case PIXEL_FORMAT_UNKNOWN: @@ -134,7 +131,6 @@ case PIXEL_FORMAT_YUV444P12: case PIXEL_FORMAT_Y8: case PIXEL_FORMAT_Y16: - case PIXEL_FORMAT_I422: return true; case PIXEL_FORMAT_YV12A: case PIXEL_FORMAT_ARGB:
diff --git a/media/base/video_types.h b/media/base/video_types.h index 8a00516..916ba61 100644 --- a/media/base/video_types.h +++ b/media/base/video_types.h
@@ -66,12 +66,9 @@ PIXEL_FORMAT_Y8 = 25, // single 8bpp plane. PIXEL_FORMAT_Y16 = 26, // single 16bpp plane. - PIXEL_FORMAT_I422 = - 27, // 16bpp YUV planar 1x1 Y, 2x1 UV samples, a.k.a. YU16. - // Please update UMA histogram enumeration when adding new formats here. PIXEL_FORMAT_MAX = - PIXEL_FORMAT_I422, // Must always be equal to largest entry logged. + PIXEL_FORMAT_Y16, // Must always be equal to largest entry logged. }; // Color space or color range used for the pixels.
diff --git a/media/blink/webmediaplayer_cast_android.cc b/media/blink/webmediaplayer_cast_android.cc index 3d801f0..06de8cf 100644 --- a/media/blink/webmediaplayer_cast_android.cc +++ b/media/blink/webmediaplayer_cast_android.cc
@@ -132,12 +132,9 @@ gl->GenMailboxCHROMIUM(texture_mailbox.name); gl->ProduceTextureDirectCHROMIUM(remote_playback_texture_id, texture_mailbox.name); - const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM(); - gl->Flush(); gpu::SyncToken texture_mailbox_sync_token; - gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, - texture_mailbox_sync_token.GetData()); + gl->GenUnverifiedSyncTokenCHROMIUM(texture_mailbox_sync_token.GetData()); gpu::MailboxHolder holders[media::VideoFrame::kMaxPlanes] = { gpu::MailboxHolder(texture_mailbox, texture_mailbox_sync_token,
diff --git a/media/filters/aom_video_decoder.cc b/media/filters/aom_video_decoder.cc index 765f5c8..a185a3fa 100644 --- a/media/filters/aom_video_decoder.cc +++ b/media/filters/aom_video_decoder.cc
@@ -52,7 +52,7 @@ case AOM_IMG_FMT_I420: return PIXEL_FORMAT_I420; case AOM_IMG_FMT_I422: - return PIXEL_FORMAT_I422; + return PIXEL_FORMAT_YV16; case AOM_IMG_FMT_I444: return PIXEL_FORMAT_YV24;
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc index 7dc4ba8..b1314a2 100644 --- a/media/filters/ffmpeg_demuxer.cc +++ b/media/filters/ffmpeg_demuxer.cc
@@ -306,7 +306,8 @@ is_enabled_(true), waiting_for_keyframe_(false), aborted_(false), - fixup_negative_timestamps_(false) { + fixup_negative_timestamps_(false), + fixup_chained_ogg_(false) { DCHECK(demuxer_); bool is_encrypted = false; @@ -515,7 +516,7 @@ // Only allow negative timestamps past if we know they'll be fixed up by the // code paths below; otherwise they should be treated as a parse error. - if ((!fixup_negative_timestamps_ || last_packet_timestamp_ == kNoTimestamp) && + if ((!fixup_chained_ogg_ || last_packet_timestamp_ == kNoTimestamp) && buffer->timestamp() < base::TimeDelta()) { MEDIA_LOG(DEBUG, media_log_) << "FFmpegDemuxer: unfixable negative timestamp"; @@ -558,8 +559,10 @@ // Fixing chained ogg is non-trivial, so for now just reuse the last good // timestamp. The decoder will rewrite the timestamps to be sample accurate // later. See http://crbug.com/396864. - if (fixup_negative_timestamps_ && - buffer->timestamp() < last_packet_timestamp_) { + // + // Note: This will not work with codecs that have out of order frames like + // H.264 with b-frames, but luckily you can't put those in ogg files... + if (fixup_chained_ogg_ && buffer->timestamp() < last_packet_timestamp_) { buffer->set_timestamp(last_packet_timestamp_ + (last_packet_duration_ != kNoTimestamp ? last_packet_duration_ @@ -1278,6 +1281,8 @@ int detected_text_track_count = 0; int supported_audio_track_count = 0; int supported_video_track_count = 0; + bool has_opus_or_vorbis_audio = false; + bool needs_negative_timestamp_fixup = false; for (size_t i = 0; i < format_context->nb_streams; ++i) { AVStream* stream = format_context->streams[i]; const AVCodecParameters* codec_parameters = stream->codecpar; @@ -1411,12 +1416,29 @@ max_duration = std::max(max_duration, streams_[i]->duration()); - const base::TimeDelta start_time = + base::TimeDelta start_time = ExtractStartTime(stream, start_time_estimates[i]); - streams_[i]->set_start_time(start_time); - if (start_time < start_time_) { + + // Note: This value is used for seeking, so we must take the true value and + // not the one possibly clamped to zero below. + if (start_time < start_time_) start_time_ = start_time; + + const bool is_opus_or_vorbis = + codec_id == AV_CODEC_ID_OPUS || codec_id == AV_CODEC_ID_VORBIS; + if (!has_opus_or_vorbis_audio) + has_opus_or_vorbis_audio = is_opus_or_vorbis; + + if (codec_type == AVMEDIA_TYPE_AUDIO && start_time < base::TimeDelta() && + is_opus_or_vorbis) { + needs_negative_timestamp_fixup = true; + + // Fixup the seeking information to avoid selecting the audio stream + // simply because it has a lower starting time. + start_time = base::TimeDelta(); } + + streams_[i]->set_start_time(start_time); } RecordDetectedTrackTypeStats(detected_audio_track_count, @@ -1445,10 +1467,16 @@ max_duration = kInfiniteDuration; } + // Chained ogg is only allowed on single track audio only opus/vorbis media. + const bool needs_chained_ogg_fixup = + glue_->container() == container_names::CONTAINER_OGG && + supported_audio_track_count == 1 && !supported_video_track_count && + has_opus_or_vorbis_audio; + // FFmpeg represents audio data marked as before the beginning of stream as // having negative timestamps. This data must be discarded after it has been // decoded, not before since it is used to warmup the decoder. There are - // currently two known cases for this: vorbis in ogg and opus in ogg and webm. + // currently two known cases for this: vorbis in ogg and opus. // // For API clarity, it was decided that the rest of the media pipeline should // not be exposed to negative timestamps. Which means we need to rebase these @@ -1461,33 +1489,20 @@ // FFmpeg's use of negative timestamps for opus pre-skip is nonstandard, but // for more information on pre-skip see section 4.2 of the Ogg Opus spec: // https://tools.ietf.org/html/draft-ietf-codec-oggopus-08#section-4.2 - for (const auto& stream : streams_) { - if (!stream || stream->type() != DemuxerStream::AUDIO) - continue; - const AVStream* audio_stream = stream->av_stream(); - DCHECK(audio_stream); - if (audio_stream->codecpar->codec_id == AV_CODEC_ID_OPUS || - (glue_->container() == container_names::CONTAINER_OGG && - audio_stream->codecpar->codec_id == AV_CODEC_ID_VORBIS)) { - for (size_t i = 0; i < streams_.size(); ++i) { - if (!streams_[i]) - continue; - streams_[i]->enable_negative_timestamp_fixups(); - - // Fixup the seeking information to avoid selecting the audio stream - // simply because it has a lower starting time. - if (streams_[i]->av_stream() == audio_stream && - streams_[i]->start_time() < base::TimeDelta()) { - streams_[i]->set_start_time(base::TimeDelta()); - } - } + if (needs_negative_timestamp_fixup || needs_chained_ogg_fixup) { + for (auto& stream : streams_) { + if (!stream) + continue; + if (needs_negative_timestamp_fixup) + stream->enable_negative_timestamp_fixups(); + if (needs_chained_ogg_fixup) + stream->enable_chained_ogg_fixups(); } } // If no start time could be determined, default to zero. - if (start_time_ == kInfiniteDuration) { + if (start_time_ == kInfiniteDuration) start_time_ = base::TimeDelta(); - } // MPEG-4 B-frames cause grief for a simple container like AVI. Enable PTS // generation so we always get timestamps, see http://crbug.com/169570
diff --git a/media/filters/ffmpeg_demuxer.h b/media/filters/ffmpeg_demuxer.h index a8c90d22..1f0e15f9 100644 --- a/media/filters/ffmpeg_demuxer.h +++ b/media/filters/ffmpeg_demuxer.h
@@ -105,6 +105,7 @@ void enable_negative_timestamp_fixups() { fixup_negative_timestamps_ = true; } + void enable_chained_ogg_fixups() { fixup_chained_ogg_ = true; } // DemuxerStream implementation. Type type() const override; @@ -197,6 +198,7 @@ std::string encryption_key_id_; bool fixup_negative_timestamps_; + bool fixup_chained_ogg_; DISALLOW_COPY_AND_ASSIGN(FFmpegDemuxerStream); };
diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc index 8b78482..2026825 100644 --- a/media/filters/ffmpeg_demuxer_unittest.cc +++ b/media/filters/ffmpeg_demuxer_unittest.cc
@@ -800,7 +800,7 @@ demuxer_->start_time()); // Though the internal start time may be below zero, the exposed media time - // must always be greater than zero. + // must always be >= zero. EXPECT_EQ(base::TimeDelta(), demuxer_->GetStartTime()); video->Read(NewReadCB(FROM_HERE, 9997, 0, true)); @@ -847,7 +847,7 @@ } // Though the internal start time may be below zero, the exposed media time - // must always be greater than zero. + // must always be >= zero. EXPECT_EQ(base::TimeDelta(), demuxer_->GetStartTime()); video->Read(NewReadCB(FROM_HERE, 16009, 0, true)); @@ -866,6 +866,59 @@ } } +#if BUILDFLAG(USE_PROPRIETARY_CODECS) +// Similar to the test above, but using an opus clip plus h264 b-frames to +// ensure we don't apply chained ogg workarounds to other content. +TEST_F(FFmpegDemuxerTest, + Read_AudioNegativeStartTimeAndOpusDiscardH264Mp4_Sync) { + CreateDemuxer("tos-h264-opus.mp4"); + InitializeDemuxer(); + + // Attempt a read from the video stream and run the message loop until done. + DemuxerStream* video = GetStream(DemuxerStream::VIDEO); + DemuxerStream* audio = GetStream(DemuxerStream::AUDIO); + EXPECT_EQ(audio->audio_decoder_config().codec_delay(), 312); + + // Packet size to timestamp (in microseconds) mapping for the first N packets + // which should be fully discarded. + static const int kTestExpectations[][2] = { + {234, 20000}, {228, 40000}, {340, 60000}}; + + // Run the test twice with a seek in between. + for (int i = 0; i < 2; ++i) { + audio->Read(NewReadCBWithCheckedDiscard( + FROM_HERE, 408, 0, base::TimeDelta::FromMicroseconds(6500), true)); + base::RunLoop().Run(); + + for (size_t j = 0; j < arraysize(kTestExpectations); ++j) { + audio->Read(NewReadCB(FROM_HERE, kTestExpectations[j][0], + kTestExpectations[j][1], true)); + base::RunLoop().Run(); + } + + // Though the internal start time may be below zero, the exposed media time + // must always be >= zero. + EXPECT_EQ(base::TimeDelta(), demuxer_->GetStartTime()); + + video->Read(NewReadCB(FROM_HERE, 185105, 0, true)); + base::RunLoop().Run(); + + video->Read(NewReadCB(FROM_HERE, 35941, 125000, false)); + base::RunLoop().Run(); + + // If things aren't working correctly, this expectation will fail because + // the chained ogg workaround breaks out of order timestamps. + video->Read(NewReadCB(FROM_HERE, 8129, 84000, false)); + base::RunLoop().Run(); + + // Seek back to the beginning and repeat the test. + WaitableMessageLoopEvent event; + demuxer_->Seek(base::TimeDelta(), event.GetPipelineStatusCB()); + event.RunAndWaitForStatus(PIPELINE_OK); + } +} +#endif + // Similar to the test above, but using sfx-opus.ogg, which has a much smaller // amount of discard padding and no |start_time| set on the AVStream. TEST_F(FFmpegDemuxerTest, Read_AudioNegativeStartTimeAndOpusSfxDiscard_Sync) { @@ -885,7 +938,7 @@ base::RunLoop().Run(); // Though the internal start time may be below zero, the exposed media time - // must always be greater than zero. + // must always be >= zero. EXPECT_EQ(base::TimeDelta(), demuxer_->GetStartTime()); // Seek back to the beginning and repeat the test.
diff --git a/media/gpu/v4l2/v4l2_device.cc b/media/gpu/v4l2/v4l2_device.cc index 8684eaf..26cc9f1 100644 --- a/media/gpu/v4l2/v4l2_device.cc +++ b/media/gpu/v4l2/v4l2_device.cc
@@ -57,7 +57,7 @@ return PIXEL_FORMAT_YV12; case V4L2_PIX_FMT_YUV422M: - return PIXEL_FORMAT_I422; + return PIXEL_FORMAT_YV16; case V4L2_PIX_FMT_RGB32: return PIXEL_FORMAT_ARGB;
diff --git a/media/remoting/proto_enum_utils.cc b/media/remoting/proto_enum_utils.cc index 2f7401a..19753da 100644 --- a/media/remoting/proto_enum_utils.cc +++ b/media/remoting/proto_enum_utils.cc
@@ -351,7 +351,6 @@ CASE_RETURN_OTHER(PIXEL_FORMAT_YUV444P12); CASE_RETURN_OTHER(PIXEL_FORMAT_Y8); CASE_RETURN_OTHER(PIXEL_FORMAT_Y16); - CASE_RETURN_OTHER(PIXEL_FORMAT_I422); } return base::nullopt; // Not a 'default' to ensure compile-time checks. } @@ -388,7 +387,6 @@ CASE_RETURN_OTHER(PIXEL_FORMAT_YUV444P12); CASE_RETURN_OTHER(PIXEL_FORMAT_Y8); CASE_RETURN_OTHER(PIXEL_FORMAT_Y16); - CASE_RETURN_OTHER(PIXEL_FORMAT_I422); } return base::nullopt; // Not a 'default' to ensure compile-time checks. }
diff --git a/media/remoting/rpc.proto b/media/remoting/rpc.proto index 8747856..fea133f 100644 --- a/media/remoting/rpc.proto +++ b/media/remoting/rpc.proto
@@ -216,7 +216,6 @@ PIXEL_FORMAT_YUV444P12 = 24; PIXEL_FORMAT_Y8 = 25; PIXEL_FORMAT_Y16 = 26; - PIXEL_FORMAT_I422 = 27; }; // Proto version of media::ColorSpace.
diff --git a/media/renderers/paint_canvas_video_renderer.cc b/media/renderers/paint_canvas_video_renderer.cc index 85865edc..bb432ee9 100644 --- a/media/renderers/paint_canvas_video_renderer.cc +++ b/media/renderers/paint_canvas_video_renderer.cc
@@ -71,9 +71,7 @@ explicit SyncTokenClientImpl(gpu::gles2::GLES2Interface* gl) : gl_(gl) {} ~SyncTokenClientImpl() override = default; void GenerateSyncToken(gpu::SyncToken* sync_token) override { - const uint64_t fence_sync = gl_->InsertFenceSyncCHROMIUM(); - gl_->ShallowFlushCHROMIUM(); - gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token->GetData()); + gl_->GenSyncTokenCHROMIUM(sync_token->GetData()); } void WaitSyncToken(const gpu::SyncToken& sync_token) override { gl_->WaitSyncTokenCHROMIUM(sync_token.GetConstData()); @@ -734,7 +732,6 @@ } break; case PIXEL_FORMAT_YV16: - case PIXEL_FORMAT_I422: LIBYUV_I422_TO_ARGB(video_frame->visible_data(VideoFrame::kYPlane), video_frame->stride(VideoFrame::kYPlane), video_frame->visible_data(VideoFrame::kUPlane), @@ -911,10 +908,7 @@ // Wait for mailbox creation on canvas context before consuming it and // copying from it on the consumer context. - const GLuint64 fence_sync = canvas_gl->InsertFenceSyncCHROMIUM(); - canvas_gl->ShallowFlushCHROMIUM(); - canvas_gl->GenSyncTokenCHROMIUM(fence_sync, - mailbox_holder.sync_token.GetData()); + canvas_gl->GenSyncTokenCHROMIUM(mailbox_holder.sync_token.GetData()); destination_gl->WaitSyncTokenCHROMIUM( mailbox_holder.sync_token.GetConstData()); @@ -930,11 +924,8 @@ // Wait for destination context to consume mailbox before deleting it in // canvas context. - const GLuint64 dest_fence_sync = destination_gl->InsertFenceSyncCHROMIUM(); - destination_gl->ShallowFlushCHROMIUM(); gpu::SyncToken dest_sync_token; - destination_gl->GenSyncTokenCHROMIUM(dest_fence_sync, - dest_sync_token.GetData()); + destination_gl->GenSyncTokenCHROMIUM(dest_sync_token.GetData()); canvas_gl->WaitSyncTokenCHROMIUM(dest_sync_token.GetConstData()); SyncTokenClientImpl client(canvas_gl);
diff --git a/media/renderers/video_overlay_factory.cc b/media/renderers/video_overlay_factory.cc index 99087698..16fdd0f7 100644 --- a/media/renderers/video_overlay_factory.cc +++ b/media/renderers/video_overlay_factory.cc
@@ -40,9 +40,7 @@ gl->GenMailboxCHROMIUM(mailbox_.name); gl->ProduceTextureDirectCHROMIUM(texture_id_, mailbox_.name); - const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM(); - gl->ShallowFlushCHROMIUM(); - gl->GenSyncTokenCHROMIUM(fence_sync, sync_token_.GetData()); + gl->GenSyncTokenCHROMIUM(sync_token_.GetData()); } } }
diff --git a/media/test/data/tos-h264-opus.mp4 b/media/test/data/tos-h264-opus.mp4 new file mode 100644 index 0000000..a2e570e --- /dev/null +++ b/media/test/data/tos-h264-opus.mp4 Binary files differ
diff --git a/media/test/pipeline_integration_test.cc b/media/test/pipeline_integration_test.cc index 9f7d1846..70e91a9 100644 --- a/media/test/pipeline_integration_test.cc +++ b/media/test/pipeline_integration_test.cc
@@ -2632,13 +2632,11 @@ ASSERT_EQ(base::TimeDelta(), demuxer_->GetStartTime()); } -// Ensures audio-video playback with missing or negative timestamps fails softly +// Ensures audio-video playback with missing or negative timestamps fails // instead of crashing. See http://crbug.com/396864. TEST_F(PipelineIntegrationTest, BasicPlaybackChainedOggVideo) { - ASSERT_EQ(PIPELINE_OK, Start("double-bear.ogv", kUnreliableDuration)); - Play(); - EXPECT_EQ(PIPELINE_ERROR_DECODE, WaitUntilEndedOrError()); - ASSERT_EQ(base::TimeDelta(), demuxer_->GetStartTime()); + ASSERT_EQ(DEMUXER_ERROR_COULD_NOT_PARSE, + Start("double-bear.ogv", kUnreliableDuration)); } // Tests that we signal ended even when audio runs longer than video track.
diff --git a/media/video/gpu_memory_buffer_video_frame_pool.cc b/media/video/gpu_memory_buffer_video_frame_pool.cc index 0d1d2d37..e587dd9 100644 --- a/media/video/gpu_memory_buffer_video_frame_pool.cc +++ b/media/video/gpu_memory_buffer_video_frame_pool.cc
@@ -459,7 +459,6 @@ case PIXEL_FORMAT_YUV444P12: case PIXEL_FORMAT_Y8: case PIXEL_FORMAT_Y16: - case PIXEL_FORMAT_I422: case PIXEL_FORMAT_UNKNOWN: frame_ready_cb.Run(video_frame); return; @@ -682,11 +681,8 @@ // Insert a sync_token, this is needed to make sure that the textures the // mailboxes refer to will be used only after all the previous commands posted // in the command buffer have been processed. - const GLuint64 fence_sync = gles2->InsertFenceSyncCHROMIUM(); - gles2->OrderingBarrierCHROMIUM(); - gpu::SyncToken sync_token; - gles2->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + gles2->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); for (size_t i = 0; i < NumGpuMemoryBuffers(output_format_); i++) mailbox_holders[i].sync_token = sync_token;
diff --git a/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc b/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc index 2f633998..f5e47f8c 100644 --- a/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc +++ b/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc
@@ -25,33 +25,18 @@ *textures = ++gen_textures_count_; } - void ShallowFlushCHROMIUM() override { - flushed_fence_sync_ = next_fence_sync_ - 1; - } - - void OrderingBarrierCHROMIUM() override { - flushed_fence_sync_ = next_fence_sync_ - 1; - } - - GLuint64 InsertFenceSyncCHROMIUM() override { return next_fence_sync_++; } - - void GenSyncTokenCHROMIUM(GLuint64 fence_sync, GLbyte* sync_token) override { + void GenSyncTokenCHROMIUM(GLbyte* sync_token) override { gpu::SyncToken sync_token_data; - if (fence_sync <= flushed_fence_sync_) { - sync_token_data.Set(gpu::CommandBufferNamespace::GPU_IO, 0, - gpu::CommandBufferId(), fence_sync); - sync_token_data.SetVerifyFlush(); - } + sync_token_data.Set(gpu::CommandBufferNamespace::GPU_IO, 0, + gpu::CommandBufferId(), next_fence_sync_++); + sync_token_data.SetVerifyFlush(); memcpy(sync_token, &sync_token_data, sizeof(sync_token_data)); } - void GenUnverifiedSyncTokenCHROMIUM(GLuint64 fence_sync, - GLbyte* sync_token) override { + void GenUnverifiedSyncTokenCHROMIUM(GLbyte* sync_token) override { gpu::SyncToken sync_token_data; - if (fence_sync <= flushed_fence_sync_) { - sync_token_data.Set(gpu::CommandBufferNamespace::GPU_IO, 0, - gpu::CommandBufferId(), fence_sync); - } + sync_token_data.Set(gpu::CommandBufferNamespace::GPU_IO, 0, + gpu::CommandBufferId(), next_fence_sync_++); memcpy(sync_token, &sync_token_data, sizeof(sync_token_data)); } @@ -69,7 +54,6 @@ private: uint64_t next_fence_sync_ = 1u; - uint64_t flushed_fence_sync_ = 0u; unsigned mailbox_ = 0u; unsigned gen_textures_count_ = 0u; unsigned deleted_textures_ = 0u;
diff --git a/net/der/parser.cc b/net/der/parser.cc index be1c484a..4a43c2f2 100644 --- a/net/der/parser.cc +++ b/net/der/parser.cc
@@ -11,34 +11,6 @@ namespace der { -namespace { - -bool TagFromCBS(unsigned tag_value, Tag* out) { - unsigned tag_number = tag_value & CBS_ASN1_TAG_NUMBER_MASK; - if (tag_number >= 31) { - // Tag can only represent small tag numbers. - return false; - } - *out = static_cast<Tag>(tag_number); - if (tag_value & CBS_ASN1_CONSTRUCTED) { - *out |= kTagConstructed; - } - switch (tag_value & CBS_ASN1_CLASS_MASK) { - case CBS_ASN1_APPLICATION: - *out |= kTagApplication; - break; - case CBS_ASN1_CONTEXT_SPECIFIC: - *out |= kTagContextSpecific; - break; - case CBS_ASN1_PRIVATE: - *out |= kTagPrivate; - break; - } - return true; -} - -} // namespace - Parser::Parser() : advance_len_(0) { CBS_init(&cbs_, nullptr, 0); } @@ -53,10 +25,11 @@ size_t header_len; unsigned tag_value; if (!CBS_get_any_asn1_element(&peeker, &tmp_out, &tag_value, &header_len) || - !CBS_skip(&tmp_out, header_len) || !TagFromCBS(tag_value, tag)) { + !CBS_skip(&tmp_out, header_len)) { return false; } advance_len_ = CBS_len(&tmp_out) + header_len; + *tag = tag_value; *out = Input(CBS_data(&tmp_out), CBS_len(&tmp_out)); return true; }
diff --git a/net/der/parser_unittest.cc b/net/der/parser_unittest.cc index d3f86fcb..6e38bb7 100644 --- a/net/der/parser_unittest.cc +++ b/net/der/parser_unittest.cc
@@ -13,12 +13,12 @@ namespace test { TEST(ParserTest, ConsumesAllBytesOfTLV) { - const uint8_t der[] = {0x04, 0x00}; + const uint8_t der[] = {0x04 /* OCTET STRING */, 0x00}; Parser parser((Input(der))); Tag tag; Input value; ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value)); - ASSERT_EQ(0x04, tag); + ASSERT_EQ(kOctetString, tag); ASSERT_FALSE(parser.HasMore()); } @@ -66,26 +66,26 @@ } TEST(ParserTest, CanSkipOptionalTagAtEndOfInput) { - const uint8_t der[] = {0x02, 0x01, 0x01}; + const uint8_t der[] = {0x02 /* INTEGER */, 0x01, 0x01}; Parser parser((Input(der))); Tag tag; Input value; ASSERT_TRUE(parser.ReadTagAndValue(&tag, &value)); bool present; - ASSERT_TRUE(parser.ReadOptionalTag(0x02, &value, &present)); + ASSERT_TRUE(parser.ReadOptionalTag(kInteger, &value, &present)); ASSERT_FALSE(present); ASSERT_FALSE(parser.HasMore()); } TEST(ParserTest, SkipOptionalTagDoesntConsumePresentNonMatchingTLVs) { - const uint8_t der[] = {0x02, 0x01, 0x01}; + const uint8_t der[] = {0x02 /* INTEGER */, 0x01, 0x01}; Parser parser((Input(der))); bool present; - ASSERT_TRUE(parser.SkipOptionalTag(0x04, &present)); + ASSERT_TRUE(parser.SkipOptionalTag(kOctetString, &present)); ASSERT_FALSE(present); - ASSERT_TRUE(parser.SkipOptionalTag(0x02, &present)); + ASSERT_TRUE(parser.SkipOptionalTag(kInteger, &present)); ASSERT_TRUE(present); ASSERT_FALSE(parser.HasMore()); }
diff --git a/net/der/tag.cc b/net/der/tag.cc index bdd5a6b..a2b00747 100644 --- a/net/der/tag.cc +++ b/net/der/tag.cc
@@ -10,10 +10,9 @@ namespace der { -Tag ContextSpecificConstructed(uint8_t class_number) { - DCHECK_EQ(class_number, class_number & kTagNumberMask); - return (class_number & kTagNumberMask) | kTagConstructed | - kTagContextSpecific; +Tag ContextSpecificConstructed(uint8_t tag_number) { + DCHECK_EQ(tag_number, tag_number & kTagNumberMask); + return (tag_number & kTagNumberMask) | kTagConstructed | kTagContextSpecific; } Tag ContextSpecificPrimitive(uint8_t base) {
diff --git a/net/der/tag.h b/net/der/tag.h index a168df66..82d3b257 100644 --- a/net/der/tag.h +++ b/net/der/tag.h
@@ -8,63 +8,66 @@ #include <stdint.h> #include "net/base/net_export.h" +#include "third_party/boringssl/src/include/openssl/bytestring.h" namespace net { namespace der { -// This Tag type represents the identifier for an ASN.1 tag as encoded with DER. -// It follows the same bit-for-bit representation (including the class, tag -// number, and primitive/constructed bit) as DER. Constants are provided for -// universal class types, and functions are provided for building context -// specific tags. Tags can also be built from the provided constants and -// bitmasks. -using Tag = uint8_t; +// This Tag type represents the identifier for an ASN.1 tag as encoded with +// DER. It matches the BoringSSL CBS and CBB in-memory representation for a +// tag. +// +// Callers must not assume it matches the DER representation for small tag +// numbers. Instead, constants are provided for universal class types, and +// functions are provided for building context specific tags. Tags can also be +// built from the provided constants and bitmasks. +using Tag = unsigned; // Universal class primitive types -const Tag kBool = 0x01; -const Tag kInteger = 0x02; -const Tag kBitString = 0x03; -const Tag kOctetString = 0x04; -const Tag kNull = 0x05; -const Tag kOid = 0x06; -const Tag kEnumerated = 0x0A; -const Tag kUtf8String = 0x0C; -const Tag kPrintableString = 0x13; -const Tag kTeletexString = 0x14; -const Tag kIA5String = 0x16; -const Tag kUtcTime = 0x17; -const Tag kGeneralizedTime = 0x18; -const Tag kUniversalString = 0x1C; -const Tag kBmpString = 0x1E; +const Tag kBool = CBS_ASN1_BOOLEAN; +const Tag kInteger = CBS_ASN1_INTEGER; +const Tag kBitString = CBS_ASN1_BITSTRING; +const Tag kOctetString = CBS_ASN1_OCTETSTRING; +const Tag kNull = CBS_ASN1_NULL; +const Tag kOid = CBS_ASN1_OBJECT; +const Tag kEnumerated = CBS_ASN1_ENUMERATED; +const Tag kUtf8String = CBS_ASN1_UTF8STRING; +const Tag kPrintableString = CBS_ASN1_PRINTABLESTRING; +const Tag kTeletexString = CBS_ASN1_T61STRING; +const Tag kIA5String = CBS_ASN1_IA5STRING; +const Tag kUtcTime = CBS_ASN1_UTCTIME; +const Tag kGeneralizedTime = CBS_ASN1_GENERALIZEDTIME; +const Tag kUniversalString = CBS_ASN1_UNIVERSALSTRING; +const Tag kBmpString = CBS_ASN1_BMPSTRING; // Universal class constructed types -const Tag kSequence = 0x30; -const Tag kSet = 0x31; +const Tag kSequence = CBS_ASN1_SEQUENCE; +const Tag kSet = CBS_ASN1_SET; // Primitive/constructed bits -const uint8_t kTagPrimitive = 0x00; -const uint8_t kTagConstructed = 0x20; +const unsigned kTagPrimitive = 0x00; +const unsigned kTagConstructed = CBS_ASN1_CONSTRUCTED; // Tag classes -const uint8_t kTagUniversal = 0x00; -const uint8_t kTagApplication = 0x40; -const uint8_t kTagContextSpecific = 0x80; -const uint8_t kTagPrivate = 0xC0; +const unsigned kTagUniversal = 0x00; +const unsigned kTagApplication = CBS_ASN1_APPLICATION; +const unsigned kTagContextSpecific = CBS_ASN1_CONTEXT_SPECIFIC; +const unsigned kTagPrivate = CBS_ASN1_PRIVATE; // Masks for the 3 components of a tag (class, primitive/constructed, number) -const uint8_t kTagNumberMask = 0x1F; -const uint8_t kTagConstructionMask = 0x20; -const uint8_t kTagClassMask = 0xC0; +const unsigned kTagNumberMask = CBS_ASN1_TAG_NUMBER_MASK; +const unsigned kTagConstructionMask = CBS_ASN1_CONSTRUCTED; +const unsigned kTagClassMask = CBS_ASN1_CLASS_MASK; // Creates the value for the outter tag of an explicitly tagged type. // // The ASN.1 keyword for this is: -// [class_number] EXPLICIT +// [tag_number] EXPLICIT // // (Note, the EXPLICIT may be omitted if the entire schema is in // EXPLICIT mode, the default) -NET_EXPORT Tag ContextSpecificConstructed(uint8_t class_number); +NET_EXPORT Tag ContextSpecificConstructed(uint8_t tag_number); NET_EXPORT Tag ContextSpecificPrimitive(uint8_t base);
diff --git a/net/reporting/OWNERS b/net/reporting/OWNERS index 5ad5dc9..510eb168 100644 --- a/net/reporting/OWNERS +++ b/net/reporting/OWNERS
@@ -1 +1 @@ -juliatuttle@chromium.org +juliatuttle@chromium.org
diff --git a/net/socket/ssl_server_socket.h b/net/socket/ssl_server_socket.h index b61e663..92d2185 100644 --- a/net/socket/ssl_server_socket.h +++ b/net/socket/ssl_server_socket.h
@@ -30,6 +30,7 @@ namespace net { struct SSLServerConfig; +class SSLPrivateKey; class X509Certificate; // A server socket that uses SSL as the transport layer. @@ -70,6 +71,11 @@ const crypto::RSAPrivateKey& key, const SSLServerConfig& ssl_config); +NET_EXPORT std::unique_ptr<SSLServerContext> CreateSSLServerContext( + X509Certificate* certificate, + scoped_refptr<SSLPrivateKey> key, + const SSLServerConfig& ssl_config); + } // namespace net #endif // NET_SOCKET_SSL_SERVER_SOCKET_H_
diff --git a/net/socket/ssl_server_socket_impl.cc b/net/socket/ssl_server_socket_impl.cc index d18290b..198f165 100644 --- a/net/socket/ssl_server_socket_impl.cc +++ b/net/socket/ssl_server_socket_impl.cc
@@ -7,7 +7,9 @@ #include <utility> #include "base/callback_helpers.h" +#include "base/lazy_instance.h" #include "base/logging.h" +#include "base/memory/weak_ptr.h" #include "base/strings/string_util.h" #include "crypto/openssl_util.h" #include "crypto/rsa_private_key.h" @@ -30,6 +32,34 @@ namespace net { +namespace { + +// This constant can be any non-negative/non-zero value (eg: it does not +// overlap with any value of the net::Error range, including net::OK). +const int kNoPendingResult = 1; + +class SocketDataIndex { + public: + static SocketDataIndex* GetInstance(); + SocketDataIndex() { + ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0); + } + + // This is the index used with SSL_get_ex_data to retrieve the owner + // SSLServerSocketImpl object from an SSL instance. + int ssl_socket_data_index_; +}; + +base::LazyInstance<SocketDataIndex>::Leaky g_ssl_socket_data_index_ = + LAZY_INSTANCE_INITIALIZER; + +// static +SocketDataIndex* SocketDataIndex::GetInstance() { + return g_ssl_socket_data_index_.Pointer(); +} + +} // namespace + class SSLServerContextImpl::SocketImpl : public SSLServerSocket, public SocketBIOAdapter::Delegate { public: @@ -81,6 +111,36 @@ static ssl_verify_result_t CertVerifyCallback(SSL* ssl, uint8_t* out_alert); ssl_verify_result_t CertVerifyCallbackImpl(uint8_t* out_alert); + static const SSL_PRIVATE_KEY_METHOD kPrivateKeyMethod; + static ssl_private_key_result_t PrivateKeySignCallback(SSL* ssl, + uint8_t* out, + size_t* out_len, + size_t max_out, + uint16_t algorithm, + const uint8_t* in, + size_t in_len); + static ssl_private_key_result_t PrivateKeyDecryptCallback(SSL* ssl, + uint8_t* out, + size_t* out_len, + size_t max_out, + const uint8_t* in, + size_t in_len); + static ssl_private_key_result_t PrivateKeyCompleteCallback(SSL* ssl, + uint8_t* out, + size_t* out_len, + size_t max_out); + + ssl_private_key_result_t PrivateKeySignCallback(uint8_t* out, + size_t* out_len, + size_t max_out, + uint16_t algorithm, + const uint8_t* in, + size_t in_len); + ssl_private_key_result_t PrivateKeyCompleteCallback(uint8_t* out, + size_t* out_len, + size_t max_out); + void OnPrivateKeyComplete(Error error, const std::vector<uint8_t>& signature); + // SocketBIOAdapter::Delegate implementation. void OnReadReady() override; void OnWriteReady() override; @@ -113,6 +173,10 @@ CompletionCallback user_read_callback_; CompletionCallback user_write_callback_; + // SSLPrivateKey signature. + int signature_result_; + std::vector<uint8_t> signature_; + // Used by Read function. scoped_refptr<IOBuffer> user_read_buf_; int user_read_buf_len_; @@ -134,6 +198,8 @@ State next_handshake_state_; bool completed_handshake_; + base::WeakPtrFactory<SocketImpl> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(SocketImpl); }; @@ -141,11 +207,13 @@ SSLServerContextImpl* context, std::unique_ptr<StreamSocket> transport_socket) : context_(context), + signature_result_(kNoPendingResult), user_read_buf_len_(0), user_write_buf_len_(0), transport_socket_(std::move(transport_socket)), next_handshake_state_(STATE_NONE), - completed_handshake_(false) { + completed_handshake_(false), + weak_factory_(this) { ssl_.reset(SSL_new(context_->ssl_ctx_.get())); SSL_set_app_data(ssl_.get(), this); } @@ -159,6 +227,108 @@ } } +// static +const SSL_PRIVATE_KEY_METHOD + SSLServerContextImpl::SocketImpl::kPrivateKeyMethod = { + &SSLServerContextImpl::SocketImpl::PrivateKeySignCallback, + &SSLServerContextImpl::SocketImpl::PrivateKeyDecryptCallback, + &SSLServerContextImpl::SocketImpl::PrivateKeyCompleteCallback, +}; + +// static +ssl_private_key_result_t +SSLServerContextImpl::SocketImpl::PrivateKeySignCallback(SSL* ssl, + uint8_t* out, + size_t* out_len, + size_t max_out, + uint16_t algorithm, + const uint8_t* in, + size_t in_len) { + DCHECK(ssl); + SSLServerContextImpl::SocketImpl* socket = + static_cast<SSLServerContextImpl::SocketImpl*>(SSL_get_ex_data( + ssl, SocketDataIndex::GetInstance()->ssl_socket_data_index_)); + DCHECK(socket); + return socket->PrivateKeySignCallback(out, out_len, max_out, algorithm, in, + in_len); +} + +// static +ssl_private_key_result_t +SSLServerContextImpl::SocketImpl::PrivateKeyDecryptCallback(SSL* ssl, + uint8_t* out, + size_t* out_len, + size_t max_out, + const uint8_t* in, + size_t in_len) { + // Decrypt is not supported. + return ssl_private_key_failure; +} + +// static +ssl_private_key_result_t +SSLServerContextImpl::SocketImpl::PrivateKeyCompleteCallback(SSL* ssl, + uint8_t* out, + size_t* out_len, + size_t max_out) { + DCHECK(ssl); + SSLServerContextImpl::SocketImpl* socket = + static_cast<SSLServerContextImpl::SocketImpl*>(SSL_get_ex_data( + ssl, SocketDataIndex::GetInstance()->ssl_socket_data_index_)); + DCHECK(socket); + return socket->PrivateKeyCompleteCallback(out, out_len, max_out); +} + +ssl_private_key_result_t +SSLServerContextImpl::SocketImpl::PrivateKeySignCallback(uint8_t* out, + size_t* out_len, + size_t max_out, + uint16_t algorithm, + const uint8_t* in, + size_t in_len) { + DCHECK(context_); + DCHECK(context_->private_key_); + signature_result_ = ERR_IO_PENDING; + context_->private_key_->Sign( + algorithm, base::make_span(in, in_len), + base::BindRepeating( + &SSLServerContextImpl::SocketImpl::OnPrivateKeyComplete, + weak_factory_.GetWeakPtr())); + return ssl_private_key_retry; +} + +ssl_private_key_result_t +SSLServerContextImpl::SocketImpl::PrivateKeyCompleteCallback(uint8_t* out, + size_t* out_len, + size_t max_out) { + if (signature_result_ == ERR_IO_PENDING) + return ssl_private_key_retry; + if (signature_result_ != OK) { + OpenSSLPutNetError(FROM_HERE, signature_result_); + return ssl_private_key_failure; + } + if (signature_.size() > max_out) { + OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED); + return ssl_private_key_failure; + } + memcpy(out, signature_.data(), signature_.size()); + *out_len = signature_.size(); + signature_.clear(); + return ssl_private_key_success; +} + +void SSLServerContextImpl::SocketImpl::OnPrivateKeyComplete( + Error error, + const std::vector<uint8_t>& signature) { + DCHECK_EQ(ERR_IO_PENDING, signature_result_); + DCHECK(signature_.empty()); + + signature_result_ = error; + if (signature_result_ == OK) + signature_ = signature; + DoHandshakeLoop(ERR_IO_PENDING); +} + int SSLServerContextImpl::SocketImpl::Handshake( const CompletionCallback& callback) { net_log_.BeginEvent(NetLogEventType::SSL_SERVER_HANDSHAKE); @@ -480,7 +650,6 @@ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); int net_error = OK; int rv = SSL_do_handshake(ssl_.get()); - if (rv == 1) { completed_handshake_ = true; STACK_OF(CRYPTO_BUFFER)* certs = SSL_get0_peer_certificates(ssl_.get()); @@ -491,6 +660,13 @@ } } else { int ssl_error = SSL_get_error(ssl_.get(), rv); + + if (ssl_error == SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) { + DCHECK(context_->private_key_); + GotoState(STATE_HANDSHAKE); + return ERR_IO_PENDING; + } + OpenSSLErrorInfo error_info; net_error = MapOpenSSLErrorWithDetails(ssl_error, err_tracer, &error_info); @@ -544,15 +720,30 @@ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); - if (!ssl_) + if (!ssl_ || + !SSL_set_ex_data(ssl_.get(), + SocketDataIndex::GetInstance()->ssl_socket_data_index_, + this)) return ERR_UNEXPECTED; // Set certificate and private key. - DCHECK(context_->cert_->cert_buffer()); - DCHECK(context_->key_->key()); - if (!SetSSLChainAndKey(ssl_.get(), context_->cert_.get(), - context_->key_->key(), nullptr)) { - return ERR_UNEXPECTED; + if (context_->key_) { + DCHECK(context_->cert_->cert_buffer()); + DCHECK(context_->key_->key()); + if (!SetSSLChainAndKey(ssl_.get(), context_->cert_.get(), + context_->key_->key(), nullptr)) { + return ERR_UNEXPECTED; + } + } else { + DCHECK(context_->private_key_); + if (!SetSSLChainAndKey(ssl_.get(), context_->cert_.get(), nullptr, + &kPrivateKeyMethod)) { + return ERR_UNEXPECTED; + } + std::vector<uint16_t> preferences = + context_->private_key_->GetAlgorithmPreferences(); + SSL_set_signing_algorithm_prefs(ssl_.get(), preferences.data(), + preferences.size()); } transport_adapter_.reset(new SocketBIOAdapter( @@ -610,8 +801,26 @@ X509Certificate* certificate, const crypto::RSAPrivateKey& key, const SSLServerConfig& ssl_server_config) { - return std::unique_ptr<SSLServerContext>( - new SSLServerContextImpl(certificate, key, ssl_server_config)); + return std::make_unique<SSLServerContextImpl>(certificate, key, + ssl_server_config); +} + +std::unique_ptr<SSLServerContext> CreateSSLServerContext( + X509Certificate* certificate, + scoped_refptr<SSLPrivateKey> key, + const SSLServerConfig& ssl_config) { + return std::make_unique<SSLServerContextImpl>(certificate, key, ssl_config); +} + +SSLServerContextImpl::SSLServerContextImpl( + X509Certificate* certificate, + scoped_refptr<net::SSLPrivateKey> key, + const SSLServerConfig& ssl_server_config) + : ssl_server_config_(ssl_server_config), + cert_(certificate), + private_key_(key) { + CHECK(private_key_); + Init(); } SSLServerContextImpl::SSLServerContextImpl( @@ -622,6 +831,10 @@ cert_(certificate), key_(key.Copy()) { CHECK(key_); + Init(); +} + +void SSLServerContextImpl::Init() { crypto::EnsureOpenSSLInit(); ssl_ctx_.reset(SSL_CTX_new(TLS_with_buffers_method())); SSL_CTX_set_session_cache_mode(ssl_ctx_.get(), SSL_SESS_CACHE_SERVER); @@ -674,7 +887,8 @@ // as the handshake hash. std::string command("DEFAULT:!SHA256:!SHA384:!AESGCM+AES256:!aPSK"); - if (ssl_server_config_.require_ecdhe) + // SSLPrivateKey only supports ECDHE-based ciphers because it lacks decrypt. + if (ssl_server_config_.require_ecdhe || (!key_ && private_key_)) command.append(":!kRSA"); // Remove any disabled ciphers. @@ -704,8 +918,7 @@ std::unique_ptr<SSLServerSocket> SSLServerContextImpl::CreateSSLServerSocket( std::unique_ptr<StreamSocket> socket) { - return std::unique_ptr<SSLServerSocket>( - new SocketImpl(this, std::move(socket))); + return std::make_unique<SocketImpl>(this, std::move(socket)); } } // namespace net
diff --git a/net/socket/ssl_server_socket_impl.h b/net/socket/ssl_server_socket_impl.h index 7e9ca96..74ffbfa 100644 --- a/net/socket/ssl_server_socket_impl.h +++ b/net/socket/ssl_server_socket_impl.h
@@ -23,6 +23,9 @@ SSLServerContextImpl(X509Certificate* certificate, const crypto::RSAPrivateKey& key, const SSLServerConfig& ssl_server_config); + SSLServerContextImpl(X509Certificate* certificate, + scoped_refptr<SSLPrivateKey> key, + const SSLServerConfig& ssl_server_config); ~SSLServerContextImpl() override; std::unique_ptr<SSLServerSocket> CreateSSLServerSocket( @@ -31,6 +34,8 @@ private: class SocketImpl; + void Init(); + bssl::UniquePtr<SSL_CTX> ssl_ctx_; // Options for the SSL socket. @@ -40,7 +45,9 @@ scoped_refptr<X509Certificate> cert_; // Private key used by the server. + // Only one representation should be set at any time. std::unique_ptr<crypto::RSAPrivateKey> key_; + const scoped_refptr<SSLPrivateKey> private_key_; }; } // namespace net
diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc index 987768ca..b4465f7 100644 --- a/net/socket/ssl_server_socket_unittest.cc +++ b/net/socket/ssl_server_socket_unittest.cc
@@ -373,6 +373,13 @@ server_private_key_ = ReadTestKey("unittest.key.bin"); ASSERT_TRUE(server_private_key_); + std::unique_ptr<crypto::RSAPrivateKey> key = + ReadTestKey("unittest.key.bin"); + ASSERT_TRUE(key); + EVP_PKEY_up_ref(key->key()); + server_ssl_private_key_ = + WrapOpenSSLPrivateKey(bssl::UniquePtr<EVP_PKEY>(key->key())); + client_ssl_config_.false_start_enabled = false; client_ssl_config_.channel_id_enabled = false; @@ -392,6 +399,16 @@ server_cert_.get(), *server_private_key_, server_ssl_config_); } + void CreateContextSSLPrivateKey() { + client_socket_.reset(); + server_socket_.reset(); + channel_1_.reset(); + channel_2_.reset(); + server_context_.reset(); + server_context_ = CreateSSLServerContext( + server_cert_.get(), server_ssl_private_key_, server_ssl_config_); + } + void CreateSockets() { client_socket_.reset(); server_socket_.reset(); @@ -489,6 +506,7 @@ std::unique_ptr<MockCTPolicyEnforcer> ct_policy_enforcer_; std::unique_ptr<SSLServerContext> server_context_; std::unique_ptr<crypto::RSAPrivateKey> server_private_key_; + scoped_refptr<SSLPrivateKey> server_ssl_private_key_; scoped_refptr<X509Certificate> server_cert_; }; @@ -1098,4 +1116,80 @@ ASSERT_THAT(server_ret, IsError(ERR_SSL_VERSION_OR_CIPHER_MISMATCH)); } +// This test executes Connect() on SSLClientSocket and Handshake() on +// SSLServerSocket to make sure handshaking between the two sockets is +// completed successfully. The server key is represented by SSLPrivateKey. +TEST_F(SSLServerSocketTest, HandshakeServerSSLPrivateKey) { + ASSERT_NO_FATAL_FAILURE(CreateContextSSLPrivateKey()); + ASSERT_NO_FATAL_FAILURE(CreateSockets()); + + TestCompletionCallback handshake_callback; + int server_ret = server_socket_->Handshake(handshake_callback.callback()); + + TestCompletionCallback connect_callback; + int client_ret = client_socket_->Connect(connect_callback.callback()); + + client_ret = connect_callback.GetResult(client_ret); + server_ret = handshake_callback.GetResult(server_ret); + + ASSERT_THAT(client_ret, IsOk()); + ASSERT_THAT(server_ret, IsOk()); + + // Make sure the cert status is expected. + SSLInfo ssl_info; + ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info)); + EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, ssl_info.cert_status); + + // The default cipher suite should be ECDHE and an AEAD. + uint16_t cipher_suite = + SSLConnectionStatusToCipherSuite(ssl_info.connection_status); + const char* key_exchange; + const char* cipher; + const char* mac; + bool is_aead; + bool is_tls13; + SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, &is_tls13, + cipher_suite); + EXPECT_TRUE(is_aead); + ASSERT_FALSE(is_tls13); + EXPECT_STREQ("ECDHE_RSA", key_exchange); +} + +// Verifies that non-ECDHE ciphers are disabled when using SSLPrivateKey as the +// server key. +TEST_F(SSLServerSocketTest, HandshakeServerSSLPrivateKeyRequireEcdhe) { + // Disable all ECDHE suites on the client side. + uint16_t kEcdheCiphers[] = { + 0xc007, // ECDHE_ECDSA_WITH_RC4_128_SHA + 0xc009, // ECDHE_ECDSA_WITH_AES_128_CBC_SHA + 0xc00a, // ECDHE_ECDSA_WITH_AES_256_CBC_SHA + 0xc011, // ECDHE_RSA_WITH_RC4_128_SHA + 0xc013, // ECDHE_RSA_WITH_AES_128_CBC_SHA + 0xc014, // ECDHE_RSA_WITH_AES_256_CBC_SHA + 0xc02b, // ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + 0xc02f, // ECDHE_RSA_WITH_AES_128_GCM_SHA256 + 0xcca8, // ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + 0xcca9, // ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + }; + client_ssl_config_.disabled_cipher_suites.assign( + kEcdheCiphers, kEcdheCiphers + arraysize(kEcdheCiphers)); + // TLS 1.3 always works with SSLPrivateKey. + client_ssl_config_.version_max = SSL_PROTOCOL_VERSION_TLS1_2; + + ASSERT_NO_FATAL_FAILURE(CreateContextSSLPrivateKey()); + ASSERT_NO_FATAL_FAILURE(CreateSockets()); + + TestCompletionCallback connect_callback; + int client_ret = client_socket_->Connect(connect_callback.callback()); + + TestCompletionCallback handshake_callback; + int server_ret = server_socket_->Handshake(handshake_callback.callback()); + + client_ret = connect_callback.GetResult(client_ret); + server_ret = handshake_callback.GetResult(server_ret); + + ASSERT_THAT(client_ret, IsError(ERR_SSL_VERSION_OR_CIPHER_MISMATCH)); + ASSERT_THAT(server_ret, IsError(ERR_SSL_VERSION_OR_CIPHER_MISMATCH)); +} + } // namespace net
diff --git a/ppapi/proxy/compositor_layer_resource.cc b/ppapi/proxy/compositor_layer_resource.cc index 40af6982..72d6757 100644 --- a/ppapi/proxy/compositor_layer_resource.cc +++ b/ppapi/proxy/compositor_layer_resource.cc
@@ -176,9 +176,7 @@ data_.texture->source_rect.point = PP_MakeFloatPoint(0.0f, 0.0f); data_.texture->source_rect.size = source_size_; - const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM(); - gl->ShallowFlushCHROMIUM(); - gl->GenSyncTokenCHROMIUM(fence_sync, data_.texture->sync_token.GetData()); + gl->GenSyncTokenCHROMIUM(data_.texture->sync_token.GetData()); // If the PP_Resource of this layer is released by the plugin, the // release_callback will be aborted immediately, but the texture or image
diff --git a/ppapi/proxy/ppapi_command_buffer_proxy.cc b/ppapi/proxy/ppapi_command_buffer_proxy.cc index 30d221c..c518f94 100644 --- a/ppapi/proxy/ppapi_command_buffer_proxy.cc +++ b/ppapi/proxy/ppapi_command_buffer_proxy.cc
@@ -192,25 +192,6 @@ return next_fence_sync_release_++; } -bool PpapiCommandBufferProxy::IsFenceSyncRelease(uint64_t release) { - return release != 0 && release < next_fence_sync_release_; -} - -bool PpapiCommandBufferProxy::IsFenceSyncFlushed(uint64_t release) { - return release <= flushed_fence_sync_release_; -} - -bool PpapiCommandBufferProxy::IsFenceSyncFlushReceived(uint64_t release) { - if (!IsFenceSyncFlushed(release)) - return false; - - if (release <= validated_fence_sync_release_) - return true; - - EnsureWorkVisible(); - return release <= validated_fence_sync_release_; -} - bool PpapiCommandBufferProxy::IsFenceSyncReleased(uint64_t release) { NOTIMPLEMENTED(); return false;
diff --git a/ppapi/proxy/ppapi_command_buffer_proxy.h b/ppapi/proxy/ppapi_command_buffer_proxy.h index 1d19758..198346a 100644 --- a/ppapi/proxy/ppapi_command_buffer_proxy.h +++ b/ppapi/proxy/ppapi_command_buffer_proxy.h
@@ -72,9 +72,6 @@ gpu::CommandBufferId GetCommandBufferID() const override; void FlushPendingWork() override; uint64_t GenerateFenceSyncRelease() override; - bool IsFenceSyncRelease(uint64_t release) override; - bool IsFenceSyncFlushed(uint64_t release) override; - bool IsFenceSyncFlushReceived(uint64_t release) override; bool IsFenceSyncReleased(uint64_t release) override; void SignalSyncToken(const gpu::SyncToken& sync_token, const base::Closure& callback) override;
diff --git a/ppapi/proxy/ppb_graphics_3d_proxy.cc b/ppapi/proxy/ppb_graphics_3d_proxy.cc index 3fb9f939..b2cd6e5 100644 --- a/ppapi/proxy/ppb_graphics_3d_proxy.cc +++ b/ppapi/proxy/ppb_graphics_3d_proxy.cc
@@ -127,11 +127,8 @@ new PpapiHostMsg_PPBGraphics3D_TakeFrontBuffer(API_ID_PPB_GRAPHICS_3D, host_resource())); - const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM(); - gl->ShallowFlushCHROMIUM(); - gpu::SyncToken new_sync_token; - gl->GenSyncTokenCHROMIUM(fence_sync, new_sync_token.GetData()); + gl->GenSyncTokenCHROMIUM(new_sync_token.GetData()); IPC::Message* msg = new PpapiHostMsg_PPBGraphics3D_SwapBuffers( API_ID_PPB_GRAPHICS_3D, host_resource(), new_sync_token, size);
diff --git a/printing/print_job_constants.cc b/printing/print_job_constants.cc index c0b4935..8f03d3a8b 100644 --- a/printing/print_job_constants.cc +++ b/printing/print_job_constants.cc
@@ -14,12 +14,6 @@ // Unique ID sent along every preview request. const char kPreviewRequestID[] = "requestID"; -// Unique ID of Print Preview initiator host. -const char kPreviewInitiatorHostId[] = "previewInitiatorHostId"; - -// Routing ID of Print Preview initiator. -const char kPreviewInitiatorRoutingId[] = "previewInitiatorRoutingId"; - // Unique ID to identify a print preview UI. const char kPreviewUIID[] = "previewUIID";
diff --git a/printing/print_job_constants.h b/printing/print_job_constants.h index 331494fc..888c6afe 100644 --- a/printing/print_job_constants.h +++ b/printing/print_job_constants.h
@@ -13,8 +13,6 @@ PRINTING_EXPORT extern const char kIsFirstRequest[]; PRINTING_EXPORT extern const char kPreviewRequestID[]; -PRINTING_EXPORT extern const char kPreviewInitiatorHostId[]; -PRINTING_EXPORT extern const char kPreviewInitiatorRoutingId[]; PRINTING_EXPORT extern const char kPreviewUIID[]; PRINTING_EXPORT extern const char kSettingCapabilities[]; PRINTING_EXPORT extern const char kSettingCloudPrintId[];
diff --git a/printing/pwg_raster_settings.h b/printing/pwg_raster_settings.h index 46f0b55..fe7ae4c 100644 --- a/printing/pwg_raster_settings.h +++ b/printing/pwg_raster_settings.h
@@ -22,6 +22,8 @@ bool rotate_all_pages; // Rasterize pages in reverse order. bool reverse_page_order; + // Rasterize pages in color. + bool use_color; }; } // namespace printing
diff --git a/remoting/host/OWNERS b/remoting/host/OWNERS index a7f8b91..ef79bb2bb 100644 --- a/remoting/host/OWNERS +++ b/remoting/host/OWNERS
@@ -1,7 +1,7 @@ per-file *_messages*.h=set noparent per-file *_messages*.h=file://ipc/SECURITY_OWNERS - -per-file *_messages.cc=set noparent + +per-file *_messages.cc=set noparent per-file *_messages.cc=file://ipc/SECURITY_OWNERS per-file *_param_traits*.*=set noparent
diff --git a/services/device/device_service.cc b/services/device/device_service.cc index de972b3..739d07d 100644 --- a/services/device/device_service.cc +++ b/services/device/device_service.cc
@@ -13,6 +13,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "device/geolocation/geolocation_context.h" +#include "device/geolocation/geolocation_provider_impl.h" #include "mojo/public/cpp/system/message_pipe.h" #include "services/device/fingerprint/fingerprint.h" #include "services/device/generic_sensor/sensor_provider_impl.h" @@ -97,6 +98,8 @@ &DeviceService::BindFingerprintRequest, base::Unretained(this))); registry_.AddInterface<mojom::GeolocationContext>(base::Bind( &DeviceService::BindGeolocationContextRequest, base::Unretained(this))); + registry_.AddInterface<mojom::GeolocationControl>(base::Bind( + &DeviceService::BindGeolocationControlRequest, base::Unretained(this))); registry_.AddInterface<mojom::PowerMonitor>(base::Bind( &DeviceService::BindPowerMonitorRequest, base::Unretained(this))); registry_.AddInterface<mojom::ScreenOrientationListener>( @@ -187,6 +190,12 @@ GeolocationContext::Create(std::move(request)); } +void DeviceService::BindGeolocationControlRequest( + mojom::GeolocationControlRequest request) { + GeolocationProviderImpl::GetInstance()->BindGeolocationControlRequest( + std::move(request)); +} + void DeviceService::BindPowerMonitorRequest( mojom::PowerMonitorRequest request) { if (!power_monitor_message_broadcaster_) {
diff --git a/services/device/device_service.h b/services/device/device_service.h index c2cfc72..55f25480 100644 --- a/services/device/device_service.h +++ b/services/device/device_service.h
@@ -9,6 +9,7 @@ #include "build/build_config.h" #include "device/geolocation/geolocation_provider_impl.h" #include "device/geolocation/public/interfaces/geolocation_context.mojom.h" +#include "device/geolocation/public/interfaces/geolocation_control.mojom.h" #include "device/screen_orientation/public/interfaces/screen_orientation.mojom.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "services/device/public/interfaces/battery_monitor.mojom.h" @@ -87,6 +88,7 @@ void BindFingerprintRequest(mojom::FingerprintRequest request); void BindGeolocationContextRequest(mojom::GeolocationContextRequest request); + void BindGeolocationControlRequest(mojom::GeolocationControlRequest request); #if defined(OS_LINUX) && defined(USE_UDEV) void BindInputDeviceManagerRequest(mojom::InputDeviceManagerRequest request);
diff --git a/services/device/manifest.json b/services/device/manifest.json index f809e68..55a05bc 100644 --- a/services/device/manifest.json +++ b/services/device/manifest.json
@@ -10,6 +10,7 @@ "device:fingerprint": [ "device::mojom::Fingerprint" ], "device:generic_sensor": [ "device::mojom::SensorProvider" ], "device:geolocation": [ "device::mojom::GeolocationContext" ], + "device:geolocation_control": [ "device::mojom::GeolocationControl" ], "device:nfc": [ "device::mojom::NFCProvider" ], "device:power_monitor": [ "device::mojom::PowerMonitor" ], "device:screen_orientation": [ "device::mojom::ScreenOrientationListener" ],
diff --git a/services/proxy_resolver/DEPS b/services/proxy_resolver/DEPS index a6458e30..8fa9d48 100644 --- a/services/proxy_resolver/DEPS +++ b/services/proxy_resolver/DEPS
@@ -1,3 +1,3 @@ -include_rules = [ - "+net", -] +include_rules = [ + "+net", +]
diff --git a/services/proxy_resolver/public/cpp/DEPS b/services/proxy_resolver/public/cpp/DEPS index 595e9c04..8fa9d48 100644 --- a/services/proxy_resolver/public/cpp/DEPS +++ b/services/proxy_resolver/public/cpp/DEPS
@@ -1,3 +1,3 @@ -include_rules = [ - "+net", -] \ No newline at end of file +include_rules = [ + "+net", +]
diff --git a/services/proxy_resolver/public/cpp/OWNERS b/services/proxy_resolver/public/cpp/OWNERS index 22a9c64..4df0c71 100644 --- a/services/proxy_resolver/public/cpp/OWNERS +++ b/services/proxy_resolver/public/cpp/OWNERS
@@ -1,4 +1,4 @@ -per-file *_struct_traits*.*=set noparent -per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS -per-file *.typemap=set noparent -per-file *.typemap=file://ipc/SECURITY_OWNERS +per-file *_struct_traits*.*=set noparent +per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS +per-file *.typemap=set noparent +per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/services/proxy_resolver/public/interfaces/OWNERS b/services/proxy_resolver/public/interfaces/OWNERS index 065863ca..08850f4 100644 --- a/services/proxy_resolver/public/interfaces/OWNERS +++ b/services/proxy_resolver/public/interfaces/OWNERS
@@ -1,2 +1,2 @@ -per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/services/shape_detection/DEPS b/services/shape_detection/DEPS index dd63880..a291000 100644 --- a/services/shape_detection/DEPS +++ b/services/shape_detection/DEPS
@@ -1,5 +1,4 @@ include_rules = [ - "+media/base/scoped_callback_runner.h", "+jni", "+skia/ext/skia_utils_mac.h", "+third_party/skia/include",
diff --git a/services/shape_detection/barcode_detection_impl_mac.mm b/services/shape_detection/barcode_detection_impl_mac.mm index 651a1ec..35f8ff2 100644 --- a/services/shape_detection/barcode_detection_impl_mac.mm +++ b/services/shape_detection/barcode_detection_impl_mac.mm
@@ -8,7 +8,6 @@ #include "base/mac/scoped_cftyperef.h" #include "base/mac/sdk_forward_declarations.h" #include "base/strings/sys_string_conversions.h" -#include "media/base/scoped_callback_runner.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "services/shape_detection/barcode_detection_impl.h" #include "services/shape_detection/detection_utils_mac.h" @@ -36,12 +35,11 @@ void BarcodeDetectionImplMac::Detect(const SkBitmap& bitmap, DetectCallback callback) { - DetectCallback scoped_callback = media::ScopedCallbackRunner( - std::move(callback), std::vector<mojom::BarcodeDetectionResultPtr>()); - base::scoped_nsobject<CIImage> ci_image = CreateCIImageFromSkBitmap(bitmap); - if (!ci_image) + if (!ci_image) { + std::move(callback).Run({}); return; + } NSArray* const features = [detector_ featuresInImage:ci_image]; @@ -69,7 +67,7 @@ result->raw_value = base::SysNSStringToUTF8(f.messageString); results.push_back(std::move(result)); } - std::move(scoped_callback).Run(std::move(results)); + std::move(callback).Run(std::move(results)); } } // namespace shape_detection
diff --git a/services/shape_detection/face_detection_impl_mac.mm b/services/shape_detection/face_detection_impl_mac.mm index b202836..7228152d 100644 --- a/services/shape_detection/face_detection_impl_mac.mm +++ b/services/shape_detection/face_detection_impl_mac.mm
@@ -5,7 +5,6 @@ #include "services/shape_detection/face_detection_impl_mac.h" #include "base/mac/scoped_cftyperef.h" -#include "media/base/scoped_callback_runner.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "services/shape_detection/detection_utils_mac.h" #include "services/shape_detection/face_detection_provider_impl.h" @@ -34,12 +33,11 @@ void FaceDetectionImplMac::Detect(const SkBitmap& bitmap, DetectCallback callback) { - DetectCallback scoped_callback = media::ScopedCallbackRunner( - std::move(callback), std::vector<mojom::FaceDetectionResultPtr>()); - base::scoped_nsobject<CIImage> ci_image = CreateCIImageFromSkBitmap(bitmap); - if (!ci_image) + if (!ci_image) { + std::move(callback).Run({}); return; + } NSArray* const features = [detector_ featuresInImage:ci_image]; const int height = bitmap.height(); @@ -80,7 +78,7 @@ results.push_back(std::move(face)); } - std::move(scoped_callback).Run(std::move(results)); + std::move(callback).Run(std::move(results)); } } // namespace shape_detection
diff --git a/services/shape_detection/face_detection_provider_win.cc b/services/shape_detection/face_detection_provider_win.cc index 7f3beac..9150b63 100644 --- a/services/shape_detection/face_detection_provider_win.cc +++ b/services/shape_detection/face_detection_provider_win.cc
@@ -12,7 +12,6 @@ #include "base/win/core_winrt_util.h" #include "base/win/scoped_hstring.h" #include "base/win/windows_version.h" -#include "media/base/scoped_callback_runner.h" #include "mojo/public/cpp/bindings/strong_binding.h" namespace shape_detection {
diff --git a/services/shape_detection/text_detection_impl_mac.mm b/services/shape_detection/text_detection_impl_mac.mm index b527bc6..bd14925 100644 --- a/services/shape_detection/text_detection_impl_mac.mm +++ b/services/shape_detection/text_detection_impl_mac.mm
@@ -8,7 +8,6 @@ #include "base/mac/scoped_cftyperef.h" #include "base/mac/sdk_forward_declarations.h" #include "base/strings/sys_string_conversions.h" -#include "media/base/scoped_callback_runner.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "services/shape_detection/detection_utils_mac.h" #include "services/shape_detection/text_detection_impl.h" @@ -36,12 +35,12 @@ void TextDetectionImplMac::Detect(const SkBitmap& bitmap, DetectCallback callback) { DCHECK(base::mac::IsAtLeastOS10_11()); - DetectCallback scoped_callback = media::ScopedCallbackRunner( - std::move(callback), std::vector<mojom::TextDetectionResultPtr>()); base::scoped_nsobject<CIImage> ci_image = CreateCIImageFromSkBitmap(bitmap); - if (!ci_image) + if (!ci_image) { + std::move(callback).Run({}); return; + } NSArray* const features = [detector_ featuresInImage:ci_image]; @@ -68,7 +67,7 @@ results.push_back(std::move(result)); } - std::move(scoped_callback).Run(std::move(results)); + std::move(callback).Run(std::move(results)); } } // namespace shape_detection
diff --git a/services/ui/public/cpp/input_devices/input_device_client.cc b/services/ui/public/cpp/input_devices/input_device_client.cc index 75eaeff..5d8de89 100644 --- a/services/ui/public/cpp/input_devices/input_device_client.cc +++ b/services/ui/public/cpp/input_devices/input_device_client.cc
@@ -61,16 +61,6 @@ observers_.RemoveObserver(observer); } -void InputDeviceClient::SetKeyboardDevicesForTesting( - const std::vector<InputDevice>& devices) { - OnKeyboardDeviceConfigurationChanged(devices); -} - -void InputDeviceClient::SetTouchscreenDevicesForTesting( - const std::vector<TouchscreenDevice>& devices) { - OnTouchscreenDeviceConfigurationChanged(devices, false); -} - InputDeviceClient::InputDeviceClient(bool is_input_device_manager) : binding_(this), is_input_device_manager_(is_input_device_manager) { if (is_input_device_manager_)
diff --git a/services/ui/public/cpp/input_devices/input_device_client.h b/services/ui/public/cpp/input_devices/input_device_client.h index b8b95c9..d3aa5c2a 100644 --- a/services/ui/public/cpp/input_devices/input_device_client.h +++ b/services/ui/public/cpp/input_devices/input_device_client.h
@@ -44,10 +44,6 @@ bool AreTouchscreenTargetDisplaysValid() const override; void AddObserver(ui::InputDeviceEventObserver* observer) override; void RemoveObserver(ui::InputDeviceEventObserver* observer) override; - void SetKeyboardDevicesForTesting( - const std::vector<InputDevice>& devices) override; - void SetTouchscreenDevicesForTesting( - const std::vector<TouchscreenDevice>& devices) override; protected: // Default constructor registers as InputDeviceManager. Can be subclassed in
diff --git a/services/ui/public/cpp/input_devices/input_device_client_test_api.cc b/services/ui/public/cpp/input_devices/input_device_client_test_api.cc index aa46100..a639ba7 100644 --- a/services/ui/public/cpp/input_devices/input_device_client_test_api.cc +++ b/services/ui/public/cpp/input_devices/input_device_client_test_api.cc
@@ -61,18 +61,21 @@ void InputDeviceClientTestApi::SetKeyboardDevices( const std::vector<InputDevice>& devices) { - if (DeviceDataManager::instance_) - DeviceDataManager::instance_->keyboard_devices_ = devices; - else - GetInputDeviceClient()->keyboard_devices_ = devices; + if (DeviceDataManager::instance_) { + DeviceDataManager::instance_->OnKeyboardDevicesUpdated(devices); + } else { + GetInputDeviceClient()->OnKeyboardDeviceConfigurationChanged(devices); + } } void InputDeviceClientTestApi::SetTouchscreenDevices( const std::vector<TouchscreenDevice>& devices) { - if (DeviceDataManager::instance_) - DeviceDataManager::instance_->touchscreen_devices_ = devices; - else - GetInputDeviceClient()->touchscreen_devices_ = devices; + if (DeviceDataManager::instance_) { + DeviceDataManager::instance_->OnTouchscreenDevicesUpdated(devices); + } else { + GetInputDeviceClient()->OnTouchscreenDeviceConfigurationChanged(devices, + false); + } } InputDeviceClient* InputDeviceClientTestApi::GetInputDeviceClient() {
diff --git a/services/ui/ws/remote_event_dispatcher.cc b/services/ui/ws/remote_event_dispatcher.cc index a652c8731..5e25b141 100644 --- a/services/ui/ws/remote_event_dispatcher.cc +++ b/services/ui/ws/remote_event_dispatcher.cc
@@ -40,6 +40,11 @@ cb.Run(false); return; } + + // If this is a mouse pointer event, then we have to also update the + // location of the cursor on the screen. + if (event->IsMousePointerEvent()) + display->platform_display()->MoveCursorTo(located_event->location()); } ignore_result(static_cast<PlatformDisplayDelegate*>(display) ->GetEventSink()
diff --git a/services/viz/public/interfaces/BUILD.gn b/services/viz/public/interfaces/BUILD.gn index 8e8d5b9..3a62fbcd 100644 --- a/services/viz/public/interfaces/BUILD.gn +++ b/services/viz/public/interfaces/BUILD.gn
@@ -32,6 +32,7 @@ "compositing/video_detector_observer.mojom", "constants.mojom", "hit_test/hit_test_region_list.mojom", + "hit_test/input_target_client.mojom", ] public_deps = [
diff --git a/services/viz/public/interfaces/hit_test/input_target_client.mojom b/services/viz/public/interfaces/hit_test/input_target_client.mojom new file mode 100644 index 0000000..dadabbce --- /dev/null +++ b/services/viz/public/interfaces/hit_test/input_target_client.mojom
@@ -0,0 +1,11 @@ +module viz.mojom; + +import "services/viz/public/interfaces/compositing/frame_sink_id.mojom"; +import "ui/gfx/geometry/mojo/geometry.mojom"; + +// Returns the hit-tested frame sink id for the given coordinates. +interface InputTargetClient { + + // Returns the FrameSinkId of the frame that the given point belongs to. + FrameSinkIdAt(gfx.mojom.Point point) => (FrameSinkId id); +};
diff --git a/skia/BUILD.gn b/skia/BUILD.gn index 70af6dcf..c7e6c47 100644 --- a/skia/BUILD.gn +++ b/skia/BUILD.gn
@@ -45,7 +45,7 @@ "//third_party/skia/include/pipe", "//third_party/skia/include/ports", "//third_party/skia/include/utils", - "//third_party/skia/third_party/vulkan", + "//third_party/vulkan/include", ] if (enable_vulkan) { include_dirs += [ "$vulkan_sdk_path/include" ] @@ -61,7 +61,10 @@ defines += [ "SK_HAS_JPEG_LIBRARY" ] } if (enable_vulkan) { - defines += [ "SK_VULKAN=1" ] + defines += [ + "SK_VULKAN_HEADER=\"../../skia/config/SkVulkanConfig.h\"", + "SK_VULKAN=1", + ] } if (is_component_build) {
diff --git a/skia/config/SkVulkanConfig.h b/skia/config/SkVulkanConfig.h new file mode 100644 index 0000000..bf27a8d --- /dev/null +++ b/skia/config/SkVulkanConfig.h
@@ -0,0 +1,25 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GrVulkanDefines_DEFINED +#define GrVulkanDefines_DEFINED + +#ifdef SK_VULKAN + +#if defined(USE_X11) +// TODO(crbug.com/582554): As Skia backs on XCB for vulkan backend +// temporarily define VK_USE_PLATFORM_XCB_KHR to avoid build break. +// Change it to VK_USE_PLATFORM_XLIB_KHR if Skia supports xlib in future. +#define VK_USE_PLATFORM_XCB_KHR +#endif + +#if defined(OS_ANDROID) +#define VK_USE_PLATFORM_ANDROID_KHR +#endif + +#include <vulkan/vulkan.h> + +#endif + +#endif
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index 7e17457..a65195e9 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -58,6 +58,12 @@ }, { "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_heap_unittests" + }, + { + "swarming": { "can_use_on_swarming_builders": true, "shards": 20 }, @@ -372,7 +378,19 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wtf_unittests" } ] }, @@ -438,6 +456,12 @@ }, { "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_heap_unittests" + }, + { + "swarming": { "can_use_on_swarming_builders": true, "shards": 20 }, @@ -752,7 +776,19 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wtf_unittests" } ] }, @@ -840,6 +876,12 @@ }, { "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_heap_unittests" + }, + { + "swarming": { "can_use_on_swarming_builders": true, "shards": 5 }, @@ -1293,6 +1335,12 @@ "can_use_on_swarming_builders": true }, "test": "wm_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wtf_unittests" } ], "isolated_scripts": [
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json index 5757aa018..dd8b39d 100644 --- a/testing/buildbot/chromium.clang.json +++ b/testing/buildbot/chromium.clang.json
@@ -7578,6 +7578,13 @@ "can_use_on_swarming_builders": true, "shards": 4 } + }, + { + "isolate_name": "webkit_python_tests", + "name": "webkit_python_tests", + "swarming": { + "can_use_on_swarming_builders": true + } } ] },
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 60d0e81..8a8de12 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -1173,6 +1173,18 @@ "swarming": { "can_use_on_swarming_builders": false }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "blink_platform_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, "test": "browser_tests" }, { @@ -1420,6 +1432,18 @@ "can_use_on_swarming_builders": false }, "test": "views_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "wtf_unittests" } ] }, @@ -1441,6 +1465,18 @@ "swarming": { "can_use_on_swarming_builders": false }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "blink_platform_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, "test": "browser_tests" }, { @@ -1694,6 +1730,18 @@ "can_use_on_swarming_builders": false }, "test": "views_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "wtf_unittests" } ], "isolated_scripts": [ @@ -1720,6 +1768,13 @@ "swarming": { "can_use_on_swarming_builders": false } + }, + { + "isolate_name": "webkit_python_tests", + "name": "webkit_python_tests", + "swarming": { + "can_use_on_swarming_builders": false + } } ] }, @@ -1741,6 +1796,18 @@ "swarming": { "can_use_on_swarming_builders": false }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "blink_platform_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, "test": "browser_tests" }, { @@ -1988,6 +2055,18 @@ "can_use_on_swarming_builders": false }, "test": "views_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "wtf_unittests" } ] }, @@ -2009,6 +2088,18 @@ "swarming": { "can_use_on_swarming_builders": false }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "blink_platform_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, "test": "browser_tests" }, { @@ -2262,6 +2353,18 @@ "can_use_on_swarming_builders": false }, "test": "views_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "wtf_unittests" } ], "isolated_scripts": [ @@ -2302,6 +2405,13 @@ "swarming": { "can_use_on_swarming_builders": false } + }, + { + "isolate_name": "webkit_python_tests", + "name": "webkit_python_tests", + "swarming": { + "can_use_on_swarming_builders": false + } } ] }, @@ -2341,6 +2451,18 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_platform_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "boringssl_crypto_tests" }, { @@ -2782,7 +2904,19 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wtf_unittests" } ] }, @@ -5740,6 +5874,13 @@ "can_use_on_swarming_builders": true, "shards": 2 } + }, + { + "isolate_name": "webkit_python_tests", + "name": "webkit_python_tests", + "swarming": { + "can_use_on_swarming_builders": true + } } ] }, @@ -6673,6 +6814,12 @@ "swarming": { "can_use_on_swarming_builders": false }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, "test": "wm_unittests" }, { @@ -7153,6 +7300,18 @@ "swarming": { "can_use_on_swarming_builders": false }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "blink_platform_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, "test": "browser_tests" }, { @@ -7387,6 +7546,18 @@ "swarming": { "can_use_on_swarming_builders": false }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, + "test": "wtf_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": false + }, "test": "zucchini_unittests" } ]
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index a6070aa..3deb12d 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -2622,6 +2622,8 @@ ], "isolated_scripts": [] }, + "GPU Android arm Builder": {}, + "GPU Android arm64 Builder": {}, "GPU Linux Builder": {}, "GPU Linux Builder (dbg)": {}, "GPU Linux Ozone Builder": {}, @@ -4603,6 +4605,451 @@ } ] }, + "Linux Release Swarmed (Intel HD 630)": { + "gtest_tests": [ + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Ubuntu" + } + ] + }, + "test": "angle_end2end_tests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0", + "--no-xvfb" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Ubuntu" + } + ] + }, + "test": "angle_unittests", + "use_xvfb": false + }, + { + "args": [ + "--enable-gpu", + "--test-launcher-bot-mode", + "--test-launcher-jobs=1", + "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*", + "--no-xvfb" + ], + "name": "tab_capture_end2end_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Ubuntu" + } + ] + }, + "test": "browser_tests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests", + "--use-cmd-decoder=validating" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Ubuntu" + } + ] + }, + "test": "gl_tests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests", + "--no-xvfb" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Ubuntu" + } + ] + }, + "test": "gl_unittests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Ubuntu" + } + ] + }, + "test": "gles2_conform_test", + "use_xvfb": false + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Ubuntu" + } + ] + }, + "test": "swiftshader_unittests", + "use_xvfb": false + } + ], + "isolated_scripts": [ + { + "args": [ + "context_lost", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "context_lost_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Ubuntu" + } + ] + } + }, + { + "args": [ + "depth_capture", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "depth_capture_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Ubuntu" + } + ] + } + }, + { + "args": [ + "gpu_process", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "gpu_process_launch_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Ubuntu" + } + ] + } + }, + { + "args": [ + "hardware_accelerated_feature", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "hardware_accelerated_feature_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Ubuntu" + } + ] + } + }, + { + "args": [ + "info_collection", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--expected-vendor-id", + "8086", + "--expected-device-id", + "5912" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "info_collection_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Ubuntu" + } + ] + } + }, + { + "args": [ + "maps", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test", + "--os-type", + "linux", + "--build-revision", + "${got_revision}", + "--test-machine-name", + "${buildername}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "maps_pixel_test", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Ubuntu" + } + ] + } + }, + { + "args": [ + "pixel", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test", + "--refimg-cloud-storage-bucket", + "chromium-gpu-archive/reference-images", + "--os-type", + "linux", + "--build-revision", + "${got_revision}", + "--test-machine-name", + "${buildername}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "pixel_test", + "non_precommit_args": [ + "--upload-refimg-to-cloud-storage" + ], + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "precommit_args": [ + "--download-refimg-from-cloud-storage" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Ubuntu" + } + ] + } + }, + { + "args": [ + "screenshot_sync", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "screenshot_sync_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Ubuntu" + } + ] + } + }, + { + "args": [ + "trace_test", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "trace_test", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Ubuntu" + } + ] + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating", + "--webgl-conformance-version=2.0.1", + "--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" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Ubuntu" + } + ], + "shards": 20 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl_conformance_gl_passthrough_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Ubuntu" + } + ], + "shards": 2 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl_conformance_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Ubuntu" + } + ], + "shards": 2 + } + } + ] + }, "Linux dEQP Release (NVIDIA)": { "gtest_tests": [ { @@ -12355,658 +12802,6 @@ } ] }, - "Win10 Release (NVIDIA Quadro P400)": { - "gtest_tests": [ - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - }, - "test": "angle_end2end_tests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests", - "--test-launcher-retry-limit=0" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - }, - "test": "angle_unittests", - "use_xvfb": false - }, - { - "args": [ - "--test-launcher-retry-limit=0" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - }, - "test": "angle_white_box_tests", - "use_xvfb": false - }, - { - "args": [ - "--enable-gpu", - "--no-xvfb", - "--test-launcher-jobs=1", - "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*" - ], - "name": "tab_capture_end2end_tests", - "swarming": { - "can_use_on_swarming_builders": false - }, - "test": "browser_tests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests", - "--use-cmd-decoder=validating" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - }, - "test": "gl_tests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests", - "--use-cmd-decoder=passthrough" - ], - "name": "gl_tests_passthrough", - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - }, - "test": "gl_tests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - }, - "test": "gl_unittests", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests", - "--use-angle=d3d9" - ], - "name": "gles2_conform_d3d9_test", - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - }, - "test": "gles2_conform_test", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests", - "--use-angle=gl", - "--disable-gpu-sandbox" - ], - "name": "gles2_conform_gl_test", - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - }, - "test": "gles2_conform_test", - "use_xvfb": false - }, - { - "args": [ - "--use-gpu-in-tests" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - }, - "test": "gles2_conform_test", - "use_xvfb": false - }, - { - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - }, - "test": "gpu_unittests", - "use_xvfb": false - }, - { - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - }, - "test": "swiftshader_unittests", - "use_xvfb": false - }, - { - "args": [ - "--use-angle=d3d11", - "--use-test-data-path", - "--test_video_data=test-25fps.h264:320:240:250:258:::1" - ], - "name": "video_decode_accelerator_d3d11_unittest", - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - }, - "test": "video_decode_accelerator_unittest", - "use_xvfb": false - }, - { - "args": [ - "--use-angle=d3d9", - "--use-test-data-path", - "--test_video_data=test-25fps.h264:320:240:250:258:::1" - ], - "name": "video_decode_accelerator_d3d9_unittest", - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - }, - "test": "video_decode_accelerator_unittest", - "use_xvfb": false - }, - { - "args": [ - "--use-angle=gl", - "--use-test-data-path", - "--test_video_data=test-25fps.h264:320:240:250:258:::1" - ], - "name": "video_decode_accelerator_gl_unittest", - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - }, - "test": "video_decode_accelerator_unittest", - "use_xvfb": false - } - ], - "isolated_scripts": [ - { - "args": [ - "context_lost", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "context_lost_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "depth_capture", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "depth_capture_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "gpu_process", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "gpu_process_launch_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "hardware_accelerated_feature", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "hardware_accelerated_feature_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "info_collection", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--expected-vendor-id", - "10de", - "--expected-device-id", - "1cb3" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "info_collection_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "maps", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--dont-restore-color-profile-after-test", - "--os-type", - "win", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "maps_pixel_test", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "pixel", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--dont-restore-color-profile-after-test", - "--refimg-cloud-storage-bucket", - "chromium-gpu-archive/reference-images", - "--os-type", - "win", - "--build-revision", - "${got_revision}", - "--test-machine-name", - "${buildername}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "pixel_test", - "non_precommit_args": [ - "--upload-refimg-to-cloud-storage" - ], - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "precommit_args": [ - "--download-refimg-from-cloud-storage" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "screenshot_sync", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", - "--dont-restore-color-profile-after-test" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "screenshot_sync_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "trace_test", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "trace_test", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ] - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating", - "--webgl-conformance-version=2.0.1", - "--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" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ], - "shards": 20 - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-cmd-decoder=passthrough" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_d3d11_passthrough_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ], - "shards": 2 - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d9 --use-cmd-decoder=passthrough" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_d3d9_passthrough_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ], - "shards": 2 - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d9 --use-cmd-decoder=validating" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_d3d9_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ], - "shards": 2 - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_gl_passthrough_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ], - "shards": 2 - } - }, - { - "args": [ - "webgl_conformance", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating" - ], - "isolate_name": "telemetry_gpu_integration_test", - "name": "webgl_conformance_tests", - "override_compile_targets": [ - "telemetry_gpu_integration_test" - ], - "swarming": { - "can_use_on_swarming_builders": false, - "dimension_sets": [ - { - "gpu": "10de:1cb3", - "os": "Windows-10" - } - ], - "shards": 2 - } - } - ] - }, "Win10 Release (NVIDIA)": { "gtest_tests": [ { @@ -13717,6 +13512,685 @@ } ] }, + "Win10 Release Swarmed (Intel HD 630)": { + "gtest_tests": [ + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + }, + "test": "angle_end2end_tests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + }, + "test": "angle_unittests", + "use_xvfb": false + }, + { + "args": [ + "--test-launcher-retry-limit=0" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + }, + "test": "angle_white_box_tests", + "use_xvfb": false + }, + { + "args": [ + "--enable-gpu", + "--test-launcher-bot-mode", + "--test-launcher-jobs=1", + "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*" + ], + "name": "tab_capture_end2end_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + }, + "test": "browser_tests", + "use_xvfb": false + }, + { + "args": [ + "--enable-gpu", + "--test-launcher-bot-mode", + "--test-launcher-jobs=1", + "--gtest_filter=VrBrowserTest.*", + "--gtest_also_run_disabled_tests" + ], + "name": "vr_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + }, + "test": "browser_tests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests", + "--use-cmd-decoder=validating" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + }, + "test": "gl_tests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests", + "--use-cmd-decoder=passthrough" + ], + "name": "gl_tests_passthrough", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + }, + "test": "gl_tests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + }, + "test": "gl_unittests", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests", + "--use-angle=d3d9" + ], + "name": "gles2_conform_d3d9_test", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + }, + "test": "gles2_conform_test", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests", + "--use-angle=gl", + "--disable-gpu-sandbox" + ], + "name": "gles2_conform_gl_test", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + }, + "test": "gles2_conform_test", + "use_xvfb": false + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + }, + "test": "gles2_conform_test", + "use_xvfb": false + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + }, + "test": "gpu_unittests", + "use_xvfb": false + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + }, + "test": "swiftshader_unittests", + "use_xvfb": false + }, + { + "args": [ + "--use-angle=d3d11", + "--use-test-data-path", + "--test_video_data=test-25fps.h264:320:240:250:258:::1" + ], + "name": "video_decode_accelerator_d3d11_unittest", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + }, + "test": "video_decode_accelerator_unittest", + "use_xvfb": false + }, + { + "args": [ + "--use-angle=d3d9", + "--use-test-data-path", + "--test_video_data=test-25fps.h264:320:240:250:258:::1" + ], + "name": "video_decode_accelerator_d3d9_unittest", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + }, + "test": "video_decode_accelerator_unittest", + "use_xvfb": false + }, + { + "args": [ + "--use-angle=gl", + "--use-test-data-path", + "--test_video_data=test-25fps.h264:320:240:250:258:::1" + ], + "name": "video_decode_accelerator_gl_unittest", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + }, + "test": "video_decode_accelerator_unittest", + "use_xvfb": false + } + ], + "isolated_scripts": [ + { + "args": [ + "context_lost", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "context_lost_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + } + }, + { + "args": [ + "depth_capture", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "depth_capture_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + } + }, + { + "args": [ + "gpu_process", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "gpu_process_launch_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + } + }, + { + "args": [ + "hardware_accelerated_feature", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "hardware_accelerated_feature_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + } + }, + { + "args": [ + "info_collection", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--expected-vendor-id", + "8086", + "--expected-device-id", + "5912" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "info_collection_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + } + }, + { + "args": [ + "maps", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test", + "--os-type", + "win", + "--build-revision", + "${got_revision}", + "--test-machine-name", + "${buildername}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "maps_pixel_test", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + } + }, + { + "args": [ + "pixel", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test", + "--refimg-cloud-storage-bucket", + "chromium-gpu-archive/reference-images", + "--os-type", + "win", + "--build-revision", + "${got_revision}", + "--test-machine-name", + "${buildername}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "pixel_test", + "non_precommit_args": [ + "--upload-refimg-to-cloud-storage" + ], + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "precommit_args": [ + "--download-refimg-from-cloud-storage" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + } + }, + { + "args": [ + "screenshot_sync", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", + "--dont-restore-color-profile-after-test" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "screenshot_sync_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + } + }, + { + "args": [ + "trace_test", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "trace_test", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ] + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating", + "--webgl-conformance-version=2.0.1", + "--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" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ], + "shards": 20 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-cmd-decoder=passthrough" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl_conformance_d3d11_passthrough_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ], + "shards": 2 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d9 --use-cmd-decoder=passthrough" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl_conformance_d3d9_passthrough_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ], + "shards": 2 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d9 --use-cmd-decoder=validating" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl_conformance_d3d9_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ], + "shards": 2 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl_conformance_gl_passthrough_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ], + "shards": 2 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl_conformance_tests", + "override_compile_targets": [ + "telemetry_gpu_integration_test" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912", + "os": "Windows-10" + } + ], + "shards": 2 + } + } + ] + }, "Win7 ANGLE Tryserver (AMD)": { "gtest_tests": [ {
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index 0b8a0be..ffc5509 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -17,6 +17,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "boringssl_crypto_tests" }, { @@ -183,6 +189,18 @@ "can_use_on_swarming_builders": true }, "test": "url_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wtf_unittests" } ] }, @@ -202,6 +220,12 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "boringssl_crypto_tests" }, { @@ -374,6 +398,18 @@ "can_use_on_swarming_builders": true }, "test": "url_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wtf_unittests" } ] }, @@ -1203,6 +1239,18 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_platform_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "boringssl_crypto_tests" }, { @@ -1721,7 +1769,19 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wtf_unittests" } ], "isolated_scripts": [ @@ -1761,6 +1821,13 @@ "can_use_on_swarming_builders": true, "shards": 4 } + }, + { + "isolate_name": "webkit_python_tests", + "name": "webkit_python_tests", + "swarming": { + "can_use_on_swarming_builders": true + } } ] }, @@ -1800,6 +1867,18 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_platform_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "boringssl_crypto_tests" }, { @@ -2123,7 +2202,19 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wtf_unittests" } ], "isolated_scripts": [ @@ -2151,6 +2242,13 @@ "can_use_on_swarming_builders": true, "shards": 4 } + }, + { + "isolate_name": "webkit_python_tests", + "name": "webkit_python_tests", + "swarming": { + "can_use_on_swarming_builders": true + } } ] }
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json index 0ebfb2a..1e7afe8 100644 --- a/testing/buildbot/chromium.mac.json +++ b/testing/buildbot/chromium.mac.json
@@ -30,6 +30,18 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_platform_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "boringssl_crypto_tests" }, { @@ -368,6 +380,18 @@ "can_use_on_swarming_builders": true }, "test": "viz_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wtf_unittests" } ], "isolated_scripts": [ @@ -421,6 +445,13 @@ ], "shards": 10 } + }, + { + "isolate_name": "webkit_python_tests", + "name": "webkit_python_tests", + "swarming": { + "can_use_on_swarming_builders": true + } } ] }, @@ -448,6 +479,18 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_platform_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "boringssl_crypto_tests" }, { @@ -774,6 +817,18 @@ "can_use_on_swarming_builders": true }, "test": "viz_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wtf_unittests" } ], "isolated_scripts": [ @@ -827,6 +882,13 @@ ], "shards": 10 } + }, + { + "isolate_name": "webkit_python_tests", + "name": "webkit_python_tests", + "swarming": { + "can_use_on_swarming_builders": true + } } ] }, @@ -852,6 +914,18 @@ }, { "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_platform_unittests" + }, + { + "swarming": { "can_use_on_swarming_builders": true, "shards": 10 }, @@ -1180,6 +1254,18 @@ "can_use_on_swarming_builders": true }, "test": "viz_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wtf_unittests" } ], "isolated_scripts": [ @@ -1234,6 +1320,13 @@ ], "shards": 12 } + }, + { + "isolate_name": "webkit_python_tests", + "name": "webkit_python_tests", + "swarming": { + "can_use_on_swarming_builders": true + } } ] }, @@ -1698,6 +1791,18 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_platform_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "boringssl_crypto_tests" }, { @@ -2037,6 +2142,18 @@ "can_use_on_swarming_builders": true }, "test": "viz_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wtf_unittests" } ], "isolated_scripts": [ @@ -2057,6 +2174,13 @@ "can_use_on_swarming_builders": true, "shards": 4 } + }, + { + "isolate_name": "webkit_python_tests", + "name": "webkit_python_tests", + "swarming": { + "can_use_on_swarming_builders": true + } } ] }
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json index 0e9c576..0664e85 100644 --- a/testing/buildbot/chromium.win.json +++ b/testing/buildbot/chromium.win.json
@@ -37,6 +37,18 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_platform_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "boringssl_crypto_tests" }, { @@ -480,12 +492,24 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" }, { "swarming": { "can_use_on_swarming_builders": true }, + "test": "wtf_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "zucchini_unittests" } ], @@ -523,6 +547,13 @@ "can_use_on_swarming_builders": true, "shards": 4 } + }, + { + "isolate_name": "webkit_python_tests", + "name": "webkit_python_tests", + "swarming": { + "can_use_on_swarming_builders": true + } } ] }, @@ -573,6 +604,18 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_platform_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "boringssl_crypto_tests" }, { @@ -1007,7 +1050,19 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "wtf_unittests" } ] }, @@ -1674,6 +1729,18 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "blink_heap_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, + "test": "blink_platform_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "boringssl_crypto_tests" }, { @@ -2077,12 +2144,24 @@ "swarming": { "can_use_on_swarming_builders": true }, + "test": "webkit_unit_tests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "wm_unittests" }, { "swarming": { "can_use_on_swarming_builders": true }, + "test": "wtf_unittests" + }, + { + "swarming": { + "can_use_on_swarming_builders": true + }, "test": "zucchini_unittests" } ], @@ -2128,6 +2207,13 @@ ], "shards": 10 } + }, + { + "isolate_name": "webkit_python_tests", + "name": "webkit_python_tests", + "swarming": { + "can_use_on_swarming_builders": true + } } ] },
diff --git a/testing/buildbot/filters/fuchsia.content_unittests.filter b/testing/buildbot/filters/fuchsia.content_unittests.filter index 522cb85..19ba29a 100644 --- a/testing/buildbot/filters/fuchsia.content_unittests.filter +++ b/testing/buildbot/filters/fuchsia.content_unittests.filter
@@ -14,9 +14,6 @@ -RendererAudioOutputStreamFactoryIntegrationTest.StreamIntegrationTest -WebContentsAudioInputStreamTest.MirroringNothingWithTargetChange/0 -# https://crbug.com/762125 --VideoCaptureBufferPoolTest.BufferPool/* - # Flaky: https://crbug.com/760687. -CacheStorageManagerTest.GetAllOriginsUsageWithOldIndex -CacheStorageManagerTest.GetOriginSizeWithOldIndex
diff --git a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter index 3d20ac79..7f6f37fe 100644 --- a/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter +++ b/testing/buildbot/filters/mojo.fyi.network_browser_tests.filter
@@ -824,3 +824,8 @@ # Prevent tests from making real network requests. # https://crbug.com/793899 -ExtensionApiTest.DoNotOpenUninstallUrlForBlacklistedExtensions + +# Session cookies tests are flaky. +# https://crbug.com/795417 +-ContinueWhereILeftOffTest.SessionCookies +-RestartTest.SessionCookies
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 6542c1e5..9853cb5b 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -224,44 +224,20 @@ 'Lollipop Consumer Tester', 'Unswarmed N5 Tests Dummy Builder', 'Unswarmed N5X Tests Dummy Builder', - # chromium.chromiumos - 'Linux ChromiumOS Tests (dbg)(1)', - 'linux-chromeos-dbg', - 'linux-chromeos-rel', # chromium.clang 'CrWinAsan', 'CrWinAsan(dll)', 'CrWinAsanCov', 'ToTLinuxMSan', # chromium.fyi - 'Chromium Mac 10.10 MacViews', - 'Chromium Mac 10.11', - 'Chromium Mac 10.11 Force Mac Toolchain', - 'Chromium Mac 10.13', - 'Chromium Win 10 GCE Tests', 'CrWinAsan tester', 'CrWinAsan(dll) tester', 'CrWinAsanCov tester', - 'Win 10 Fast Ring', - # On chromium.linux, unclear why these only run on "Linux Tests". - 'Cast Audio Linux', - 'Cast Linux', - 'Linux Tests (dbg)(1)', - 'Linux Tests (dbg)(1)(32)', - # On chromium.mac, unclear why these only run on "Mac10.9 Tests". - 'Mac10.10 Tests', - 'Mac10.11 Tests', - 'Mac10.12 Tests', - 'Mac10.9 Tests (dbg)', # chromium.memory 'Linux Chromium OS ASan LSan Tests (1)', 'Linux ChromiumOS MSan Tests', 'Linux MSan Tests', 'Linux TSan Tests', - # On chromium.win, unclear why these only run on "Win7 Tests (1)". - 'Win 7 Tests x64 (1)', - 'Win10 Tests x64', - 'Win7 Tests (dbg)(1)', ], 'modifications': { # chromium.android @@ -296,27 +272,9 @@ 'CrWinAsanCov', 'ToTLinuxMSan', # chromium.fyi - 'Chromium Mac 10.10 MacViews', - 'Chromium Mac 10.11', - 'Chromium Mac 10.11 Force Mac Toolchain', - 'Chromium Mac 10.13', - 'Chromium Win 10 GCE Tests', 'CrWinAsan tester', 'CrWinAsan(dll) tester', 'CrWinAsanCov tester', - 'Win 10 Fast Ring', - # On chromium.linux, unclear why these only run on "Linux Tests". - 'Linux Tests (dbg)(1)', - 'Linux Tests (dbg)(1)(32)', - # On chromium.mac, unclear why these only run on "Mac10.9 Tests". - 'Mac10.10 Tests', - 'Mac10.11 Tests', - 'Mac10.12 Tests', - 'Mac10.9 Tests (dbg)', - # On chromium.win, unclear why these only run on "Win7 Tests (1)". - 'Win 7 Tests x64 (1)', - 'Win10 Tests x64', - 'Win7 Tests (dbg)(1)', ], }, 'boringssl_crypto_tests': { @@ -4347,26 +4305,6 @@ }, }, }, - 'webkit_python_tests': { - 'remove_from': [ - # chromium.clang - 'ToTMac', - # chromium.fyi - 'Chromium Mac 10.11', - 'Chromium Mac 10.13', - 'Out of Process Profiling Mac', - # On chromium.linux, unclear why these only run on "Linux Tests". - 'Linux Tests (dbg)(1)', - 'Linux Tests (dbg)(1)(32)', - # On chromium.mac, unclear why these only run on "Mac10.9 Tests". - 'Mac10.10 Tests', - 'Mac10.11 Tests', - 'Mac10.12 Tests', - 'Mac10.9 Tests (dbg)', - 'Win 7 Tests x64 (1)', - 'Win7 Tests (dbg)(1)', - ], - }, 'webkit_unit_tests': { 'remove_from': [ # On chromium.android, unclear why these aren't run. @@ -4387,10 +4325,6 @@ 'Unswarmed N5 Tests Dummy Builder', 'Unswarmed N5X Tests Dummy Builder', 'x86 Cloud Tester', - # chromium.chromiumos - 'Linux ChromiumOS Tests (dbg)(1)', - 'linux-chromeos-dbg', - 'linux-chromeos-rel', # chromium.clang 'CrWinAsan', 'CrWinAsan(dll)', @@ -4399,34 +4333,15 @@ 'ToTLinuxMSan', 'ToTLinuxThinLTO', # chromium.fyi - 'Chromium Mac 10.10 MacViews', - 'Chromium Mac 10.11', - 'Chromium Mac 10.11 Force Mac Toolchain', - 'Chromium Mac 10.13', - 'Chromium Win 10 GCE Tests', 'CrWinAsan tester', 'CrWinAsan(dll) tester', 'CrWinAsanCov tester', - 'ThinLTO Linux ToT', - 'Win 10 Fast Ring', - # On chromium.linux, unclear why these only run on "Linux Tests". - 'Cast Audio Linux', - 'Cast Linux', - 'Linux Tests (dbg)(1)', - 'Linux Tests (dbg)(1)(32)', - # On chromium.mac, unclear why these only run on "Mac10.9 Tests". - 'Mac10.10 Tests', - 'Mac10.11 Tests', - 'Mac10.12 Tests', - 'Mac10.9 Tests (dbg)', + # chromium.chromiumos + 'linux-chromeos-rel', # crbug.com/795440 # chromium.memory 'Linux Chromium OS ASan LSan Tests (1)', 'Linux ChromiumOS MSan Tests', 'Linux MSan Tests', - # chromium.win - 'Win 7 Tests x64 (1)', - 'Win10 Tests x64', - 'Win7 Tests (dbg)(1)', ], 'modifications': { # chromium.memory @@ -4582,10 +4497,6 @@ 'Unswarmed N5 Tests Dummy Builder', 'Unswarmed N5X Tests Dummy Builder', 'x86 Cloud Tester', - # chromium.chromiumos - 'Linux ChromiumOS Tests (dbg)(1)', - 'linux-chromeos-dbg', - 'linux-chromeos-rel', # chromium.clang 'CrWinAsan', 'CrWinAsan(dll)', @@ -4593,34 +4504,14 @@ 'ToTAndroidCFI', 'ToTLinuxMSan', # chromium.fyi - 'Chromium Mac 10.10 MacViews', - 'Chromium Mac 10.11', - 'Chromium Mac 10.11 Force Mac Toolchain', - 'Chromium Mac 10.13', - 'Chromium Win 10 GCE Tests', 'CrWinAsan tester', 'CrWinAsan(dll) tester', 'CrWinAsanCov tester', - 'Win 10 Fast Ring', - # On chromium.linux, unclear why these only run on "Linux Tests". - 'Cast Audio Linux', - 'Cast Linux', - 'Linux Tests (dbg)(1)', - 'Linux Tests (dbg)(1)(32)', - # On chromium.mac, unclear why these only run on "Mac10.9 Tests". - 'Mac10.10 Tests', - 'Mac10.11 Tests', - 'Mac10.12 Tests', - 'Mac10.9 Tests (dbg)', # chromium.memory 'Linux Chromium OS ASan LSan Tests (1)', 'Linux ChromiumOS MSan Tests', 'Linux MSan Tests', 'Linux TSan Tests', - # On chromium.win, unclear why these only run on "Win7 Tests (1)". - 'Win 7 Tests x64 (1)', - 'Win10 Tests x64', - 'Win7 Tests (dbg)(1)', ], }, 'zucchini_unittests': {
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG index aa87157..ac154a96 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -127,53 +127,53 @@ crbug.com/591099 animations/interpolation/webkit-column-width-interpolation.html [ Pass ] crbug.com/591099 animations/lazy-detached-animation-stop.html [ Failure ] crbug.com/591099 animations/rotate-transform-equivalent.html [ Failure ] -crbug.com/591099 animations/skew-notsequential-compositor.html [ Failure ] +crbug.com/591099 animations/skew-notsequential-compositor.html [ Failure Pass ] crbug.com/591099 animations/stability/element-animate-float-crash.html [ Failure ] crbug.com/591099 animations/state-at-end-event.html [ Failure ] -crbug.com/591099 animations/timing/animation-duration-infinite.html [ Failure ] +crbug.com/591099 animations/timing/animation-duration-infinite.html [ Failure Pass ] crbug.com/591099 animations/timing/timing-model.html [ Pass Timeout ] crbug.com/591099 bindings/blink-in-js-asan-crash.html [ Failure ] -crbug.com/591099 compositing/absolute-inside-out-of-view-fixed.html [ Failure ] -crbug.com/591099 compositing/animation/busy-indicator.html [ Failure ] +crbug.com/591099 compositing/absolute-inside-out-of-view-fixed.html [ Failure Pass ] +crbug.com/591099 compositing/animation/busy-indicator.html [ Failure Pass ] crbug.com/591099 compositing/animation/state-at-end-event-transform-layer.html [ Failure ] -crbug.com/591099 compositing/checkerboard.html [ Failure ] +crbug.com/591099 compositing/checkerboard.html [ Failure Pass ] crbug.com/591099 compositing/child-transform-layer-requires-box.html [ Failure ] -crbug.com/591099 compositing/clip-child-by-non-stacking-ancestor.html [ Failure ] +crbug.com/591099 compositing/clip-child-by-non-stacking-ancestor.html [ Failure Pass ] crbug.com/591099 compositing/color-matching/image-color-matching.html [ Failure ] -crbug.com/591099 compositing/columns/composited-in-paginated.html [ Failure ] -crbug.com/591099 compositing/composited-scaled-child-with-border-radius-parent-clip.html [ Failure ] -crbug.com/591099 compositing/composited-translated-child-with-border-radius-parent-clip.html [ Failure ] +crbug.com/591099 compositing/columns/composited-in-paginated.html [ Failure Pass ] +crbug.com/591099 compositing/composited-scaled-child-with-border-radius-parent-clip.html [ Failure Pass ] +crbug.com/591099 compositing/composited-translated-child-with-border-radius-parent-clip.html [ Failure Pass ] crbug.com/591099 compositing/compositing-visible-descendant.html [ Failure ] -crbug.com/591099 compositing/contents-opaque/background-clip.html [ Failure ] -crbug.com/591099 compositing/contents-opaque/background-color.html [ Failure ] +crbug.com/591099 compositing/contents-opaque/background-clip.html [ Failure Pass ] +crbug.com/591099 compositing/contents-opaque/background-color.html [ Failure Pass ] crbug.com/591099 compositing/contents-opaque/body-background-painted.html [ Failure ] crbug.com/591099 compositing/contents-opaque/body-background-skipped.html [ Failure ] -crbug.com/591099 compositing/contents-opaque/filter.html [ Failure ] -crbug.com/591099 compositing/contents-opaque/hidden-with-visible-child.html [ Failure ] -crbug.com/591099 compositing/contents-opaque/hidden-with-visible-text.html [ Failure ] -crbug.com/591099 compositing/contents-opaque/layer-opacity.html [ Failure ] -crbug.com/591099 compositing/contents-opaque/layer-transform.html [ Failure ] -crbug.com/591099 compositing/contents-opaque/overflow-hidden-child-layers.html [ Failure ] +crbug.com/591099 compositing/contents-opaque/filter.html [ Failure Pass ] +crbug.com/591099 compositing/contents-opaque/hidden-with-visible-child.html [ Failure Pass ] +crbug.com/591099 compositing/contents-opaque/hidden-with-visible-text.html [ Failure Pass ] +crbug.com/591099 compositing/contents-opaque/layer-opacity.html [ Failure Pass ] +crbug.com/591099 compositing/contents-opaque/layer-transform.html [ Failure Pass ] +crbug.com/591099 compositing/contents-opaque/overflow-hidden-child-layers.html [ Failure Pass ] crbug.com/591099 compositing/direct-image-compositing.html [ Failure ] crbug.com/591099 compositing/draws-content/canvas-background-layer.html [ Failure ] crbug.com/591099 compositing/draws-content/webgl-background-layer.html [ Failure ] -crbug.com/591099 compositing/filters/sw-layer-overlaps-hw-shadow.html [ Failure ] -crbug.com/591099 compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow.html [ Failure ] -crbug.com/591099 compositing/filters/sw-shadow-overlaps-hw-layer.html [ Failure ] -crbug.com/591099 compositing/filters/sw-shadow-overlaps-hw-shadow.html [ Failure ] -crbug.com/591099 compositing/fixed-position-changed-to-absolute.html [ Failure ] +crbug.com/591099 compositing/filters/sw-layer-overlaps-hw-shadow.html [ Failure Pass ] +crbug.com/591099 compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow.html [ Failure Pass ] +crbug.com/591099 compositing/filters/sw-shadow-overlaps-hw-layer.html [ Failure Pass ] +crbug.com/591099 compositing/filters/sw-shadow-overlaps-hw-shadow.html [ Failure Pass ] +crbug.com/591099 compositing/fixed-position-changed-to-absolute.html [ Failure Pass ] crbug.com/591099 compositing/framesets/composited-frame-alignment.html [ Failure ] crbug.com/591099 compositing/generated-content.html [ Failure ] crbug.com/591099 compositing/geometry/abs-position-inside-opacity.html [ Failure ] -crbug.com/591099 compositing/geometry/ancestor-overflow-change.html [ Failure ] -crbug.com/591099 compositing/geometry/bounds-clipped-composited-child.html [ Failure ] -crbug.com/591099 compositing/geometry/bounds-ignores-hidden-composited-descendant.html [ Failure ] -crbug.com/591099 compositing/geometry/bounds-ignores-hidden-dynamic-negzindex.html [ Failure ] +crbug.com/591099 compositing/geometry/ancestor-overflow-change.html [ Failure Pass ] +crbug.com/591099 compositing/geometry/bounds-clipped-composited-child.html [ Failure Pass ] +crbug.com/591099 compositing/geometry/bounds-ignores-hidden-composited-descendant.html [ Failure Pass ] +crbug.com/591099 compositing/geometry/bounds-ignores-hidden-dynamic-negzindex.html [ Failure Pass ] crbug.com/591099 compositing/geometry/bounds-ignores-hidden-dynamic.html [ Failure ] crbug.com/591099 compositing/geometry/bounds-ignores-hidden.html [ Failure ] -crbug.com/591099 compositing/geometry/clip-inside.html [ Failure ] -crbug.com/591099 compositing/geometry/clip-with-shadow.html [ Failure ] -crbug.com/591099 compositing/geometry/clip.html [ Failure ] +crbug.com/591099 compositing/geometry/clip-inside.html [ Failure Pass ] +crbug.com/591099 compositing/geometry/clip-with-shadow.html [ Failure Pass ] +crbug.com/591099 compositing/geometry/clip.html [ Failure Pass ] crbug.com/591099 compositing/geometry/clipping-foreground.html [ Crash Failure ] crbug.com/591099 compositing/geometry/composited-html-size.html [ Failure ] crbug.com/591099 compositing/geometry/composited-in-columns.html [ Failure ] @@ -183,27 +183,27 @@ crbug.com/591099 compositing/geometry/fixed-position-transform-composited-page-scale-down.html [ Failure ] crbug.com/591099 compositing/geometry/fixed-position-transform-composited-page-scale.html [ Failure ] crbug.com/591099 compositing/geometry/fixed-position.html [ Failure ] -crbug.com/591099 compositing/geometry/flipped-writing-mode.html [ Failure ] +crbug.com/591099 compositing/geometry/flipped-writing-mode.html [ Failure Pass ] crbug.com/591099 compositing/geometry/foreground-layer.html [ Crash Failure ] -crbug.com/591099 compositing/geometry/horizontal-scroll-composited.html [ Failure ] -crbug.com/591099 compositing/geometry/layer-due-to-layer-children-deep-switch.html [ Failure ] +crbug.com/591099 compositing/geometry/horizontal-scroll-composited.html [ Failure Pass ] +crbug.com/591099 compositing/geometry/layer-due-to-layer-children-deep-switch.html [ Failure Pass ] crbug.com/591099 compositing/geometry/layer-due-to-layer-children-deep.html [ Failure ] -crbug.com/591099 compositing/geometry/layer-due-to-layer-children-switch.html [ Failure ] +crbug.com/591099 compositing/geometry/layer-due-to-layer-children-switch.html [ Failure Pass ] crbug.com/591099 compositing/geometry/layer-due-to-layer-children.html [ Failure ] -crbug.com/591099 compositing/geometry/limit-layer-bounds-opacity-transition.html [ Failure ] -crbug.com/591099 compositing/geometry/limit-layer-bounds-overflow-root.html [ Failure ] -crbug.com/591099 compositing/geometry/limit-layer-bounds-positioned-transition.html [ Failure ] -crbug.com/591099 compositing/geometry/limit-layer-bounds-positioned.html [ Failure ] -crbug.com/591099 compositing/geometry/limit-layer-bounds-transformed.html [ Failure ] +crbug.com/591099 compositing/geometry/limit-layer-bounds-opacity-transition.html [ Failure Pass ] +crbug.com/591099 compositing/geometry/limit-layer-bounds-overflow-root.html [ Failure Pass ] +crbug.com/591099 compositing/geometry/limit-layer-bounds-positioned-transition.html [ Failure Pass ] +crbug.com/591099 compositing/geometry/limit-layer-bounds-positioned.html [ Failure Pass ] +crbug.com/591099 compositing/geometry/limit-layer-bounds-transformed.html [ Failure Pass ] crbug.com/591099 compositing/geometry/outline-change.html [ Failure ] crbug.com/591099 compositing/geometry/partial-layout-update.html [ Failure ] -crbug.com/591099 compositing/geometry/preserve-3d-switching.html [ Failure ] +crbug.com/591099 compositing/geometry/preserve-3d-switching.html [ Failure Pass ] crbug.com/591099 compositing/geometry/repaint-foreground-layer.html [ Crash Failure ] crbug.com/591099 compositing/geometry/root-layer-update.html [ Failure ] -crbug.com/591099 compositing/geometry/tall-page-composited.html [ Failure ] +crbug.com/591099 compositing/geometry/tall-page-composited.html [ Failure Pass ] crbug.com/591099 compositing/geometry/transformed-abs-position-inside-composited.html [ Failure ] crbug.com/591099 compositing/geometry/transfrom-origin-on-zero-size-layer.html [ Failure ] -crbug.com/591099 compositing/geometry/vertical-scroll-composited.html [ Failure ] +crbug.com/591099 compositing/geometry/vertical-scroll-composited.html [ Failure Pass ] crbug.com/591099 compositing/geometry/video-fixed-scrolling.html [ Failure ] crbug.com/591099 compositing/geometry/video-opacity-overlay.html [ Failure ] crbug.com/591099 compositing/gestures/gesture-tapHighlight-2-iframe-composited-outer.html [ Failure ] @@ -213,134 +213,134 @@ crbug.com/591099 compositing/gestures/gesture-tapHighlight-2-iframe-scrolled-outer.html [ Failure ] crbug.com/591099 compositing/gestures/gesture-tapHighlight-2-iframe.html [ Failure ] crbug.com/591099 compositing/gestures/gesture-tapHighlight-img-and-text-2.html [ Failure ] -crbug.com/591099 compositing/iframes/become-composited-nested-iframes.html [ Failure ] -crbug.com/591099 compositing/iframes/become-overlapped-iframe.html [ Failure ] +crbug.com/591099 compositing/iframes/become-composited-nested-iframes.html [ Failure Pass ] +crbug.com/591099 compositing/iframes/become-overlapped-iframe.html [ Failure Pass ] crbug.com/591099 compositing/iframes/composited-iframe-alignment.html [ Failure ] -crbug.com/591099 compositing/iframes/composited-iframe-scroll.html [ Failure ] -crbug.com/591099 compositing/iframes/composited-parent-iframe.html [ Failure ] -crbug.com/591099 compositing/iframes/connect-compositing-iframe-delayed.html [ Failure ] -crbug.com/591099 compositing/iframes/connect-compositing-iframe.html [ Failure ] -crbug.com/591099 compositing/iframes/connect-compositing-iframe2.html [ Failure ] -crbug.com/591099 compositing/iframes/connect-compositing-iframe3.html [ Failure ] -crbug.com/591099 compositing/iframes/enter-compositing-iframe.html [ Failure ] +crbug.com/591099 compositing/iframes/composited-iframe-scroll.html [ Failure Pass ] +crbug.com/591099 compositing/iframes/composited-parent-iframe.html [ Failure Pass ] +crbug.com/591099 compositing/iframes/connect-compositing-iframe-delayed.html [ Failure Pass ] +crbug.com/591099 compositing/iframes/connect-compositing-iframe.html [ Failure Pass ] +crbug.com/591099 compositing/iframes/connect-compositing-iframe2.html [ Failure Pass ] +crbug.com/591099 compositing/iframes/connect-compositing-iframe3.html [ Failure Pass ] +crbug.com/591099 compositing/iframes/enter-compositing-iframe.html [ Failure Pass ] crbug.com/591099 compositing/iframes/floating-self-painting-frame.html [ Failure ] -crbug.com/591099 compositing/iframes/iframe-content-flipping.html [ Failure ] +crbug.com/591099 compositing/iframes/iframe-content-flipping.html [ Failure Pass ] crbug.com/591099 compositing/iframes/iframe-copy-on-scroll.html [ Failure ] crbug.com/591099 compositing/iframes/iframe-in-composited-layer.html [ Failure ] -crbug.com/591099 compositing/iframes/iframe-resize.html [ Failure ] -crbug.com/591099 compositing/iframes/iframe-size-from-zero.html [ Failure ] -crbug.com/591099 compositing/iframes/invisible-iframe.html [ Failure ] -crbug.com/591099 compositing/iframes/invisible-nested-iframe-hide.html [ Failure ] -crbug.com/591099 compositing/iframes/invisible-nested-iframe-show.html [ Failure ] -crbug.com/591099 compositing/iframes/invisible-nested-iframe.html [ Failure ] +crbug.com/591099 compositing/iframes/iframe-resize.html [ Failure Pass ] +crbug.com/591099 compositing/iframes/iframe-size-from-zero.html [ Failure Pass ] +crbug.com/591099 compositing/iframes/invisible-iframe.html [ Failure Pass ] +crbug.com/591099 compositing/iframes/invisible-nested-iframe-hide.html [ Failure Pass ] +crbug.com/591099 compositing/iframes/invisible-nested-iframe-show.html [ Failure Pass ] +crbug.com/591099 compositing/iframes/invisible-nested-iframe.html [ Failure Pass ] crbug.com/591099 compositing/iframes/layout-on-compositing-change.html [ Failure ] crbug.com/591099 compositing/iframes/nested-iframe-scrolling.html [ Failure ] -crbug.com/591099 compositing/iframes/overlapped-iframe-iframe.html [ Failure ] -crbug.com/591099 compositing/iframes/overlapped-iframe.html [ Failure ] -crbug.com/591099 compositing/iframes/overlapped-nested-iframes.html [ Failure ] -crbug.com/591099 compositing/iframes/resizer.html [ Failure ] -crbug.com/591099 compositing/iframes/scrolling-iframe.html [ Failure ] +crbug.com/591099 compositing/iframes/overlapped-iframe-iframe.html [ Failure Pass ] +crbug.com/591099 compositing/iframes/overlapped-iframe.html [ Failure Pass ] +crbug.com/591099 compositing/iframes/overlapped-nested-iframes.html [ Failure Pass ] +crbug.com/591099 compositing/iframes/resizer.html [ Failure Pass ] +crbug.com/591099 compositing/iframes/scrolling-iframe.html [ Failure Pass ] crbug.com/591099 compositing/images/direct-image-background-color.html [ Failure ] crbug.com/591099 compositing/images/direct-svg-image.html [ Failure ] crbug.com/591099 compositing/img-layer-object-fit.html [ Failure ] -crbug.com/591099 compositing/layer-creation/animation-overlap-with-children.html [ Failure ] -crbug.com/591099 compositing/layer-creation/assumed-overlap-for-inline-transform.html [ Failure ] -crbug.com/591099 compositing/layer-creation/fixed-position-and-transform.html [ Failure ] -crbug.com/591099 compositing/layer-creation/fixed-position-change-out-of-view-in-view.html [ Failure ] -crbug.com/591099 compositing/layer-creation/fixed-position-in-fixed-overflow.html [ Failure ] -crbug.com/591099 compositing/layer-creation/fixed-position-no-content.html [ Failure ] -crbug.com/591099 compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers.html [ Failure ] -crbug.com/591099 compositing/layer-creation/fixed-position-nonscrollable-body-overlap.html [ Failure ] +crbug.com/591099 compositing/layer-creation/animation-overlap-with-children.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/assumed-overlap-for-inline-transform.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/fixed-position-and-transform.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/fixed-position-change-out-of-view-in-view.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/fixed-position-in-fixed-overflow.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/fixed-position-no-content.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/fixed-position-nonscrollable-body-overlap.html [ Failure Pass ] crbug.com/591099 compositing/layer-creation/fixed-position-nonscrollable-iframes-in-scrollable-page.html [ Failure ] -crbug.com/591099 compositing/layer-creation/fixed-position-out-of-view-positioning.html [ Failure ] -crbug.com/591099 compositing/layer-creation/fixed-position-out-of-view-scaled-scroll.html [ Failure ] -crbug.com/591099 compositing/layer-creation/fixed-position-out-of-view-scaled.html [ Failure ] -crbug.com/591099 compositing/layer-creation/fixed-position-out-of-view-with-backdrop-filter.html [ Failure ] -crbug.com/591099 compositing/layer-creation/fixed-position-out-of-view.html [ Failure ] -crbug.com/591099 compositing/layer-creation/fixed-position-under-transform.html [ Failure ] -crbug.com/591099 compositing/layer-creation/no-compositing-for-fixed-position-under-transform.html [ Failure ] -crbug.com/591099 compositing/layer-creation/no-compositing-for-preserve-3d.html [ Failure ] -crbug.com/591099 compositing/layer-creation/overflow-scroll-overlap.html [ Failure ] -crbug.com/591099 compositing/layer-creation/overlap-animation-clipping.html [ Failure ] -crbug.com/591099 compositing/layer-creation/overlap-animation-container.html [ Failure ] -crbug.com/591099 compositing/layer-creation/overlap-animation.html [ Failure ] -crbug.com/591099 compositing/layer-creation/overlap-child-layer.html [ Failure ] -crbug.com/591099 compositing/layer-creation/overlap-clipping.html [ Failure ] -crbug.com/591099 compositing/layer-creation/overlap-transformed-3d.html [ Failure ] -crbug.com/591099 compositing/layer-creation/overlap-transformed-and-clipped.html [ Failure ] +crbug.com/591099 compositing/layer-creation/fixed-position-out-of-view-positioning.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/fixed-position-out-of-view-scaled-scroll.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/fixed-position-out-of-view-scaled.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/fixed-position-out-of-view-with-backdrop-filter.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/fixed-position-out-of-view.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/fixed-position-under-transform.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/no-compositing-for-fixed-position-under-transform.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/no-compositing-for-preserve-3d.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/overflow-scroll-overlap.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/overlap-animation-clipping.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/overlap-animation-container.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/overlap-animation.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/overlap-child-layer.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/overlap-clipping.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/overlap-transformed-3d.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/overlap-transformed-and-clipped.html [ Failure Pass ] crbug.com/591099 compositing/layer-creation/overlap-transformed-layer-with-transform-body.html [ Failure ] -crbug.com/591099 compositing/layer-creation/overlap-transformed-layer.html [ Failure ] -crbug.com/591099 compositing/layer-creation/overlap-transformed-preserved-3d.html [ Failure ] -crbug.com/591099 compositing/layer-creation/overlap-transforms.html [ Failure ] -crbug.com/591099 compositing/layer-creation/remove-clipping-layer-with-no-children.html [ Failure ] +crbug.com/591099 compositing/layer-creation/overlap-transformed-layer.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/overlap-transformed-preserved-3d.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/overlap-transforms.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/remove-clipping-layer-with-no-children.html [ Failure Pass ] crbug.com/591099 compositing/layer-creation/rotate3d-overlap.html [ Failure ] -crbug.com/591099 compositing/layer-creation/scroll-partial-update.html [ Failure ] -crbug.com/591099 compositing/layer-creation/spanOverlapsCanvas.html [ Failure ] -crbug.com/591099 compositing/layer-creation/squashing-into-ancestor-clipping-layer-change.html [ Failure ] -crbug.com/591099 compositing/layer-creation/stacking-context-overlap-nested.html [ Failure ] -crbug.com/591099 compositing/layer-creation/stacking-context-overlap.html [ Failure ] -crbug.com/591099 compositing/layer-creation/translatez-added.html [ Failure ] -crbug.com/591099 compositing/layer-creation/translatez-overlap.html [ Failure ] +crbug.com/591099 compositing/layer-creation/scroll-partial-update.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/spanOverlapsCanvas.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/squashing-into-ancestor-clipping-layer-change.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/stacking-context-overlap-nested.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/stacking-context-overlap.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/translatez-added.html [ Failure Pass ] +crbug.com/591099 compositing/layer-creation/translatez-overlap.html [ Failure Pass ] crbug.com/591099 compositing/layers-inside-overflow-scroll.html [ Failure ] -crbug.com/591099 compositing/lots-of-img-layers-with-opacity.html [ Failure ] -crbug.com/591099 compositing/lots-of-img-layers.html [ Failure ] +crbug.com/591099 compositing/lots-of-img-layers-with-opacity.html [ Failure Pass ] +crbug.com/591099 compositing/lots-of-img-layers.html [ Failure Pass ] crbug.com/591099 compositing/masks/direct-image-mask.html [ Failure ] -crbug.com/591099 compositing/masks/mask-layer-size.html [ Failure ] -crbug.com/591099 compositing/masks/mask-of-clipped-layer.html [ Failure ] +crbug.com/591099 compositing/masks/mask-layer-size.html [ Failure Pass ] +crbug.com/591099 compositing/masks/mask-of-clipped-layer.html [ Failure Pass ] crbug.com/591099 compositing/masks/mask-with-added-filters.html [ Failure ] crbug.com/591099 compositing/masks/mask-with-removed-filters.html [ Failure ] crbug.com/591099 compositing/masks/masked-ancestor.html [ Failure ] crbug.com/591099 compositing/masks/multiple-masks.html [ Failure ] crbug.com/591099 compositing/masks/simple-composited-mask.html [ Failure ] -crbug.com/591099 compositing/nested-border-radius-composited-child.html [ Failure ] -crbug.com/591099 compositing/opacity-with-mask.html [ Failure ] -crbug.com/591099 compositing/overflow/accelerated-overflow-scroll-should-not-affect-perspective.html [ Failure ] +crbug.com/591099 compositing/nested-border-radius-composited-child.html [ Failure Pass ] +crbug.com/591099 compositing/opacity-with-mask.html [ Failure Pass ] +crbug.com/591099 compositing/overflow/accelerated-overflow-scroll-should-not-affect-perspective.html [ Failure Pass ] crbug.com/591099 compositing/overflow/accelerated-scrolling-with-clip-path-text.html [ Failure ] crbug.com/591099 compositing/overflow/accelerated-scrolling-with-clip-path.html [ Failure ] crbug.com/591099 compositing/overflow/ancestor-overflow.html [ Failure ] crbug.com/591099 compositing/overflow/border-radius-on-grandparent-composited-grandchild.html [ Failure ] crbug.com/591099 compositing/overflow/border-radius-on-parent-composited-grandchild.html [ Failure ] crbug.com/591099 compositing/overflow/border-radius-on-two-ancestors-composited-grandchild.html [ Failure ] -crbug.com/591099 compositing/overflow/border-radius-outside-bounds-of-compositing-ancestor.html [ Failure ] +crbug.com/591099 compositing/overflow/border-radius-outside-bounds-of-compositing-ancestor.html [ Failure Pass ] crbug.com/591099 compositing/overflow/border-radius-styles-with-composited-child.html [ Failure ] -crbug.com/591099 compositing/overflow/clear-scroll-parent.html [ Failure ] -crbug.com/591099 compositing/overflow/clip-descendents.html [ Failure ] +crbug.com/591099 compositing/overflow/clear-scroll-parent.html [ Failure Pass ] +crbug.com/591099 compositing/overflow/clip-descendents.html [ Failure Pass ] crbug.com/591099 compositing/overflow/clip-parent-reset.html [ Failure ] -crbug.com/591099 compositing/overflow/clipping-ancestor-with-accelerated-scrolling-ancestor.html [ Failure ] +crbug.com/591099 compositing/overflow/clipping-ancestor-with-accelerated-scrolling-ancestor.html [ Failure Pass ] crbug.com/591099 compositing/overflow/composited-layer-under-border-radius-under-composited-layer.html [ Failure ] -crbug.com/591099 compositing/overflow/composited-scrolling-paint-phases.html [ Failure ] -crbug.com/591099 compositing/overflow/content-gains-scrollbars.html [ Failure ] -crbug.com/591099 compositing/overflow/content-loses-scrollbars.html [ Failure ] +crbug.com/591099 compositing/overflow/composited-scrolling-paint-phases.html [ Failure Pass ] +crbug.com/591099 compositing/overflow/content-gains-scrollbars.html [ Failure Pass ] +crbug.com/591099 compositing/overflow/content-loses-scrollbars.html [ Failure Pass ] crbug.com/591099 compositing/overflow/fixed-position-ancestor-clip.html [ Failure ] -crbug.com/591099 compositing/overflow/fractional-sized-scrolling-layer.html [ Failure ] +crbug.com/591099 compositing/overflow/fractional-sized-scrolling-layer.html [ Failure Pass ] crbug.com/591099 compositing/overflow/grandchild-composited-with-border-radius-ancestor.html [ Failure ] crbug.com/591099 compositing/overflow/grandchild-with-border-radius-ancestor.html [ Failure ] crbug.com/591099 compositing/overflow/mask-with-filter.html [ Failure ] crbug.com/591099 compositing/overflow/mask-with-small-content-rect.html [ Failure ] crbug.com/591099 compositing/overflow/nested-border-radius-clipping.html [ Failure ] -crbug.com/591099 compositing/overflow/nested-render-surfaces-with-intervening-clip.html [ Failure ] -crbug.com/591099 compositing/overflow/nested-render-surfaces-with-rotation.html [ Failure ] -crbug.com/591099 compositing/overflow/nested-render-surfaces.html [ Failure ] +crbug.com/591099 compositing/overflow/nested-render-surfaces-with-intervening-clip.html [ Failure Pass ] +crbug.com/591099 compositing/overflow/nested-render-surfaces-with-rotation.html [ Failure Pass ] +crbug.com/591099 compositing/overflow/nested-render-surfaces.html [ Failure Pass ] crbug.com/591099 compositing/overflow/nested-scrolling.html [ Failure ] -crbug.com/591099 compositing/overflow/no-excessive-clip-parent-if-parent-escaped.html [ Failure ] -crbug.com/591099 compositing/overflow/overflow-clip-with-accelerated-scrolling-ancestor.html [ Failure ] +crbug.com/591099 compositing/overflow/no-excessive-clip-parent-if-parent-escaped.html [ Failure Pass ] +crbug.com/591099 compositing/overflow/overflow-clip-with-accelerated-scrolling-ancestor.html [ Failure Pass ] crbug.com/591099 compositing/overflow/overflow-compositing-descendant.html [ Failure ] crbug.com/591099 compositing/overflow/overflow-positioning.html [ Failure ] crbug.com/591099 compositing/overflow/overflow-scroll-with-local-image-background.html [ Failure ] crbug.com/591099 compositing/overflow/overflow-scroll.html [ Failure ] -crbug.com/591099 compositing/overflow/overflow-scrollbar-layers.html [ Failure ] +crbug.com/591099 compositing/overflow/overflow-scrollbar-layers.html [ Failure Pass ] crbug.com/591099 compositing/overflow/parent-overflow.html [ Failure ] crbug.com/591099 compositing/overflow/remove-overflow-crash2.html [ Failure ] -crbug.com/591099 compositing/overflow/reparented-scrollbars-non-sc-anc.html [ Failure ] -crbug.com/591099 compositing/overflow/resize-painting.html [ Failure ] +crbug.com/591099 compositing/overflow/reparented-scrollbars-non-sc-anc.html [ Failure Pass ] +crbug.com/591099 compositing/overflow/resize-painting.html [ Failure Pass ] crbug.com/591099 compositing/overflow/scaled-mask.html [ Failure ] -crbug.com/591099 compositing/overflow/scaled-overflow.html [ Failure ] +crbug.com/591099 compositing/overflow/scaled-overflow.html [ Failure Pass ] crbug.com/591099 compositing/overflow/scroll-ancestor-update.html [ Failure ] -crbug.com/591099 compositing/overflow/scroll-neg-z-index-and-composited-child.html [ Failure ] -crbug.com/591099 compositing/overflow/scroll-parent-absolute-with-backdrop-filter.html [ Failure ] -crbug.com/591099 compositing/overflow/scroll-parent-absolute.html [ Failure ] -crbug.com/591099 compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor.html [ Failure ] -crbug.com/591099 compositing/overflow/scrollbar-layer-placement.html [ Failure ] +crbug.com/591099 compositing/overflow/scroll-neg-z-index-and-composited-child.html [ Failure Pass ] +crbug.com/591099 compositing/overflow/scroll-parent-absolute-with-backdrop-filter.html [ Failure Pass ] +crbug.com/591099 compositing/overflow/scroll-parent-absolute.html [ Failure Pass ] +crbug.com/591099 compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor.html [ Failure Pass ] +crbug.com/591099 compositing/overflow/scrollbar-layer-placement.html [ Failure Pass ] crbug.com/591099 compositing/overflow/scrollbar-painting.html [ Failure ] crbug.com/591099 compositing/overflow/scrolling-content-clip-to-viewport.html [ Failure ] crbug.com/591099 compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped.html [ Failure ] @@ -351,17 +351,17 @@ crbug.com/591099 compositing/overflow/tiled-mask.html [ Failure ] crbug.com/591099 compositing/overflow/universal-accelerated-overflow-scroll.html [ Failure Timeout ] crbug.com/591099 compositing/overflow/update-widget-positions-on-nested-frames-and-scrollers.html [ Failure ] -crbug.com/591099 compositing/overflow/zero-size-overflow.html [ Failure ] +crbug.com/591099 compositing/overflow/zero-size-overflow.html [ Failure Pass ] crbug.com/591099 compositing/overlap-blending/children-opacity-huge.html [ Failure ] crbug.com/591099 compositing/overlap-blending/children-opacity-no-overlap.html [ Failure ] crbug.com/591099 compositing/overlap-blending/reflection-opacity-huge.html [ Failure ] -crbug.com/591099 compositing/plugins/webplugin-alpha.html [ Failure ] -crbug.com/591099 compositing/plugins/webplugin-no-alpha.html [ Failure ] -crbug.com/591099 compositing/plugins/webplugin-reflection.html [ Failure ] -crbug.com/591099 compositing/reflections/backface-hidden-reflection.html [ Failure ] +crbug.com/591099 compositing/plugins/webplugin-alpha.html [ Failure Pass ] +crbug.com/591099 compositing/plugins/webplugin-no-alpha.html [ Failure Pass ] +crbug.com/591099 compositing/plugins/webplugin-reflection.html [ Failure Pass ] +crbug.com/591099 compositing/reflections/backface-hidden-reflection.html [ Failure Pass ] crbug.com/591099 compositing/reflections/compositing-change-inside-reflection.html [ Failure ] crbug.com/591099 compositing/reflections/deeply-nested-reflections.html [ Failure ] -crbug.com/591099 compositing/reflections/enable-disable-compositing-reflection.html [ Failure ] +crbug.com/591099 compositing/reflections/enable-disable-compositing-reflection.html [ Failure Pass ] crbug.com/591099 compositing/reflections/load-video-in-reflection.html [ Failure ] crbug.com/591099 compositing/reflections/masked-reflection-on-composited.html [ Failure ] crbug.com/591099 compositing/reflections/nested-reflection-mask-change.html [ Failure ] @@ -381,78 +381,78 @@ crbug.com/591099 compositing/reflections/simple-composited-reflections.html [ Failure ] crbug.com/591099 compositing/reflections/transform-inside-reflection.html [ Failure ] crbug.com/591099 compositing/render-surface-alpha-blending.html [ Failure ] -crbug.com/591099 compositing/rendering-contexts.html [ Failure ] -crbug.com/591099 compositing/rounded-corners.html [ Failure ] -crbug.com/591099 compositing/rtl/rtl-absolute-overflow-scrolled.html [ Failure ] -crbug.com/591099 compositing/rtl/rtl-absolute-overflow.html [ Failure ] +crbug.com/591099 compositing/rendering-contexts.html [ Failure Pass ] +crbug.com/591099 compositing/rounded-corners.html [ Failure Pass ] +crbug.com/591099 compositing/rtl/rtl-absolute-overflow-scrolled.html [ Failure Pass ] +crbug.com/591099 compositing/rtl/rtl-absolute-overflow.html [ Failure Pass ] crbug.com/591099 compositing/rtl/rtl-absolute.html [ Failure ] crbug.com/591099 compositing/rtl/rtl-and-writing-mode-scrolling.html [ Failure ] -crbug.com/591099 compositing/rtl/rtl-fixed-overflow-scrolled.html [ Failure ] -crbug.com/591099 compositing/rtl/rtl-fixed-overflow.html [ Failure ] +crbug.com/591099 compositing/rtl/rtl-fixed-overflow-scrolled.html [ Failure Pass ] +crbug.com/591099 compositing/rtl/rtl-fixed-overflow.html [ Failure Pass ] crbug.com/591099 compositing/rtl/rtl-fixed.html [ Failure ] -crbug.com/591099 compositing/rtl/rtl-iframe-absolute-overflow-scrolled.html [ Failure ] -crbug.com/591099 compositing/rtl/rtl-iframe-absolute-overflow.html [ Failure ] +crbug.com/591099 compositing/rtl/rtl-iframe-absolute-overflow-scrolled.html [ Failure Pass ] +crbug.com/591099 compositing/rtl/rtl-iframe-absolute-overflow.html [ Failure Pass ] crbug.com/591099 compositing/rtl/rtl-iframe-absolute.html [ Failure ] -crbug.com/591099 compositing/rtl/rtl-iframe-fixed-overflow-scrolled.html [ Failure ] -crbug.com/591099 compositing/rtl/rtl-iframe-fixed-overflow.html [ Failure ] +crbug.com/591099 compositing/rtl/rtl-iframe-fixed-overflow-scrolled.html [ Failure Pass ] +crbug.com/591099 compositing/rtl/rtl-iframe-fixed-overflow.html [ Failure Pass ] crbug.com/591099 compositing/rtl/rtl-iframe-fixed.html [ Failure ] -crbug.com/591099 compositing/rtl/rtl-iframe-relative.html [ Failure ] +crbug.com/591099 compositing/rtl/rtl-iframe-relative.html [ Failure Pass ] crbug.com/591099 compositing/rtl/rtl-overflow-scrolling.html [ Failure ] -crbug.com/591099 compositing/rtl/rtl-relative.html [ Failure ] +crbug.com/591099 compositing/rtl/rtl-relative.html [ Failure Pass ] crbug.com/591099 compositing/self-painting-layers.html [ Failure ] crbug.com/591099 compositing/shadows/shadow-drawing.html [ Failure ] crbug.com/591099 compositing/sibling-positioning.html [ Failure ] crbug.com/591099 compositing/squashing/add-remove-squashed-layers.html [ Failure ] -crbug.com/591099 compositing/squashing/clipping-ancestor.html [ Failure ] -crbug.com/591099 compositing/squashing/composited-bounds-for-negative-z.html [ Failure ] -crbug.com/591099 compositing/squashing/do-not-squash-non-self-painting-layer.html [ Failure ] -crbug.com/591099 compositing/squashing/dont-squash-into-iframes.html [ Failure ] -crbug.com/591099 compositing/squashing/dont-squash-into-videos.html [ Failure ] -crbug.com/591099 compositing/squashing/iframes-are-never-squashed.html [ Failure ] -crbug.com/591099 compositing/squashing/invalidations-with-large-negative-margin-inline-content.html [ Failure ] -crbug.com/591099 compositing/squashing/invisible-layers-should-not-affect-geometry.html [ Failure ] -crbug.com/591099 compositing/squashing/move-squashing-layer.html [ Failure ] -crbug.com/591099 compositing/squashing/no-squashing-for-filters.html [ Failure ] -crbug.com/591099 compositing/squashing/no-squashing-into-another-clip-layer.html [ Failure ] -crbug.com/591099 compositing/squashing/no-squashing-into-fixed-position-that-clips.html [ Failure ] -crbug.com/591099 compositing/squashing/opacity-squashed-owner.html [ Failure ] -crbug.com/591099 compositing/squashing/repaint-child-of-squashed.html [ Failure ] +crbug.com/591099 compositing/squashing/clipping-ancestor.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/composited-bounds-for-negative-z.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/do-not-squash-non-self-painting-layer.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/dont-squash-into-iframes.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/dont-squash-into-videos.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/iframes-are-never-squashed.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/invalidations-with-large-negative-margin-inline-content.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/invisible-layers-should-not-affect-geometry.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/move-squashing-layer.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/no-squashing-for-filters.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/no-squashing-into-another-clip-layer.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/no-squashing-into-fixed-position-that-clips.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/opacity-squashed-owner.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/repaint-child-of-squashed.html [ Failure Pass ] crbug.com/591099 compositing/squashing/selection-repaint-with-gaps.html [ Crash Failure ] crbug.com/591099 compositing/squashing/squash-above-fixed-1.html [ Failure ] -crbug.com/591099 compositing/squashing/squash-above-fixed-2.html [ Failure ] +crbug.com/591099 compositing/squashing/squash-above-fixed-2.html [ Failure Pass ] crbug.com/591099 compositing/squashing/squash-above-fixed-3.html [ Failure ] -crbug.com/591099 compositing/squashing/squash-compositing-hover.html [ Failure ] +crbug.com/591099 compositing/squashing/squash-compositing-hover.html [ Failure Pass ] crbug.com/591099 compositing/squashing/squash-onto-distant-relative.html [ Crash ] -crbug.com/591099 compositing/squashing/squash-onto-nephew.html [ Failure ] -crbug.com/591099 compositing/squashing/squash-onto-transform-backing.html [ Failure ] -crbug.com/591099 compositing/squashing/squash-paint-invalidation-fixed-position.html [ Failure ] -crbug.com/591099 compositing/squashing/squash-same-transform-ancestor.html [ Failure ] -crbug.com/591099 compositing/squashing/squash-simple.html [ Failure ] -crbug.com/591099 compositing/squashing/squash-three-layers.html [ Failure ] -crbug.com/591099 compositing/squashing/squash-transform-repainting-child.html [ Failure ] +crbug.com/591099 compositing/squashing/squash-onto-nephew.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/squash-onto-transform-backing.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/squash-paint-invalidation-fixed-position.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/squash-same-transform-ancestor.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/squash-simple.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/squash-three-layers.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/squash-transform-repainting-child.html [ Failure Pass ] crbug.com/591099 compositing/squashing/squash-transform-repainting-transformed-child.html [ Failure ] -crbug.com/591099 compositing/squashing/squash-transform.html [ Failure ] +crbug.com/591099 compositing/squashing/squash-transform.html [ Failure Pass ] crbug.com/591099 compositing/squashing/squashed-layer-loses-graphicslayer.html [ Failure ] -crbug.com/591099 compositing/squashing/squashed-repaints.html [ Failure ] -crbug.com/591099 compositing/squashing/squashing-inside-perspective.html [ Failure ] -crbug.com/591099 compositing/squashing/squashing-print.html [ Failure ] -crbug.com/591099 compositing/squashing/squashing-sparsity-heuristic.html [ Failure ] +crbug.com/591099 compositing/squashing/squashed-repaints.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/squashing-inside-perspective.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/squashing-print.html [ Failure Pass ] +crbug.com/591099 compositing/squashing/squashing-sparsity-heuristic.html [ Failure Pass ] crbug.com/591099 compositing/squashing/vertical-writing-mode-squashed.html [ Failure ] crbug.com/591099 compositing/text-on-large-layer.html [ Failure ] -crbug.com/591099 compositing/tiled-layers-hidpi.html [ Failure ] -crbug.com/591099 compositing/update-paint-phases.html [ Failure ] +crbug.com/591099 compositing/tiled-layers-hidpi.html [ Failure Pass ] +crbug.com/591099 compositing/update-paint-phases.html [ Failure Pass ] crbug.com/591099 compositing/video-frame-size-change.html [ Failure ] crbug.com/591099 compositing/video/video-controls-layer-creation.html [ Failure ] -crbug.com/591099 compositing/visibility/layer-visible-content.html [ Failure ] -crbug.com/591099 compositing/visibility/visibility-composited-transforms.html [ Failure ] -crbug.com/591099 compositing/visibility/visibility-composited.html [ Failure ] -crbug.com/591099 compositing/visibility/visibility-image-layers-dynamic.html [ Failure ] -crbug.com/591099 compositing/visibility/visibility-on-distant-descendant.html [ Failure ] +crbug.com/591099 compositing/visibility/layer-visible-content.html [ Failure Pass ] +crbug.com/591099 compositing/visibility/visibility-composited-transforms.html [ Failure Pass ] +crbug.com/591099 compositing/visibility/visibility-composited.html [ Failure Pass ] +crbug.com/591099 compositing/visibility/visibility-image-layers-dynamic.html [ Failure Pass ] +crbug.com/591099 compositing/visibility/visibility-on-distant-descendant.html [ Failure Pass ] crbug.com/591099 compositing/webgl/webgl-background-color.html [ Failure ] crbug.com/591099 compositing/webgl/webgl-nonpremultiplied-blend.html [ Failure ] crbug.com/591099 compositing/webgl/webgl-reflection.html [ Failure ] -crbug.com/591099 compositing/will-change/composited-layers.html [ Failure ] -crbug.com/591099 compositing/z-order/negative-z-index.html [ Failure ] +crbug.com/591099 compositing/will-change/composited-layers.html [ Failure Pass ] +crbug.com/591099 compositing/z-order/negative-z-index.html [ Failure Pass ] crbug.com/591099 crypto/subtle/hkdf/cloneKey.html [ Timeout ] crbug.com/591099 crypto/subtle/hmac/cloneKey.html [ Timeout ] crbug.com/591099 crypto/subtle/pbkdf2/cloneKey.html [ Timeout ] @@ -556,8 +556,8 @@ crbug.com/591099 css1/units/length_units.html [ Failure ] crbug.com/591099 css1/units/percentage_units.html [ Failure ] crbug.com/591099 css1/units/urls.html [ Failure ] -crbug.com/591099 css2.1/20110323/abspos-non-replaced-width-margin-000.htm [ Failure ] -crbug.com/591099 css2.1/20110323/abspos-replaced-width-margin-000.htm [ Failure ] +crbug.com/591099 css2.1/20110323/abspos-non-replaced-width-margin-000.htm [ Failure Pass ] +crbug.com/591099 css2.1/20110323/abspos-replaced-width-margin-000.htm [ Failure Pass ] crbug.com/591099 css2.1/20110323/background-intrinsic-001.htm [ Failure ] crbug.com/591099 css2.1/20110323/background-intrinsic-002.htm [ Failure ] crbug.com/591099 css2.1/20110323/background-intrinsic-003.htm [ Failure ] @@ -1078,45 +1078,45 @@ crbug.com/591099 css2.1/t170602-bdr-conflct-w-97-d.html [ Failure ] crbug.com/591099 css2.1/t170602-bdr-conflct-w-98-d.html [ Failure ] crbug.com/591099 css2.1/t170602-bdr-conflct-w-99-d.html [ Failure ] -crbug.com/591099 css3/background/background-color-gradient-alignment.html [ Failure ] +crbug.com/591099 css3/background/background-color-gradient-alignment.html [ Failure Pass ] crbug.com/591099 css3/background/background-large-position-and-size-remains-stable.html [ Failure ] -crbug.com/591099 css3/blending/background-blend-mode-crossfade-image-gradient.html [ Failure ] -crbug.com/591099 css3/blending/background-blend-mode-data-uri-svg-image.html [ Failure ] -crbug.com/591099 css3/blending/background-blend-mode-default-value.html [ Failure ] -crbug.com/591099 css3/blending/background-blend-mode-different-image-formats.html [ Failure ] -crbug.com/591099 css3/blending/background-blend-mode-gif-color-2.html [ Failure ] -crbug.com/591099 css3/blending/background-blend-mode-gif-color.html [ Failure ] -crbug.com/591099 css3/blending/background-blend-mode-gradient-color.html [ Failure ] -crbug.com/591099 css3/blending/background-blend-mode-gradient-gradient.html [ Failure ] -crbug.com/591099 css3/blending/background-blend-mode-gradient-image.html [ Failure ] -crbug.com/591099 css3/blending/background-blend-mode-image-color.html [ Failure ] -crbug.com/591099 css3/blending/background-blend-mode-image-image.html [ Failure ] -crbug.com/591099 css3/blending/background-blend-mode-image-svg.html [ Failure ] -crbug.com/591099 css3/blending/background-blend-mode-multiple-background-layers.html [ Failure ] -crbug.com/591099 css3/blending/background-blend-mode-opaque-layer.html [ Failure ] +crbug.com/591099 css3/blending/background-blend-mode-crossfade-image-gradient.html [ Failure Pass ] +crbug.com/591099 css3/blending/background-blend-mode-data-uri-svg-image.html [ Failure Pass ] +crbug.com/591099 css3/blending/background-blend-mode-default-value.html [ Failure Pass ] +crbug.com/591099 css3/blending/background-blend-mode-different-image-formats.html [ Failure Pass ] +crbug.com/591099 css3/blending/background-blend-mode-gif-color-2.html [ Failure Pass ] +crbug.com/591099 css3/blending/background-blend-mode-gif-color.html [ Failure Pass ] +crbug.com/591099 css3/blending/background-blend-mode-gradient-color.html [ Failure Pass ] +crbug.com/591099 css3/blending/background-blend-mode-gradient-gradient.html [ Failure Pass ] +crbug.com/591099 css3/blending/background-blend-mode-gradient-image.html [ Failure Pass ] +crbug.com/591099 css3/blending/background-blend-mode-image-color.html [ Failure Pass ] +crbug.com/591099 css3/blending/background-blend-mode-image-image.html [ Failure Pass ] +crbug.com/591099 css3/blending/background-blend-mode-image-svg.html [ Failure Pass ] +crbug.com/591099 css3/blending/background-blend-mode-multiple-background-layers.html [ Failure Pass ] +crbug.com/591099 css3/blending/background-blend-mode-opaque-layer.html [ Failure Pass ] crbug.com/591099 css3/blending/background-blend-mode-overlapping-accelerated-elements.html [ Failure ] -crbug.com/591099 css3/blending/background-blend-mode-separate-layer-declaration.html [ Failure ] -crbug.com/591099 css3/blending/background-blend-mode-single-layer-no-blending.html [ Failure ] -crbug.com/591099 css3/blending/background-blend-mode-svg-color.html [ Failure ] +crbug.com/591099 css3/blending/background-blend-mode-separate-layer-declaration.html [ Failure Pass ] +crbug.com/591099 css3/blending/background-blend-mode-single-layer-no-blending.html [ Failure Pass ] +crbug.com/591099 css3/blending/background-blend-mode-svg-color.html [ Failure Pass ] crbug.com/591099 css3/blending/mix-blend-mode-2nd-stacking-context-composited.html [ Failure ] -crbug.com/591099 css3/blending/mix-blend-mode-composited-layers.html [ Failure ] +crbug.com/591099 css3/blending/mix-blend-mode-composited-layers.html [ Failure Pass ] crbug.com/591099 css3/blending/mix-blend-mode-composited-reason-children.html [ Failure ] crbug.com/591099 css3/blending/mix-blend-mode-isolated-group-1.html [ Failure ] -crbug.com/591099 css3/blending/mix-blend-mode-isolated-group-2.html [ Failure ] -crbug.com/591099 css3/blending/mix-blend-mode-isolated-group-3.html [ Failure ] +crbug.com/591099 css3/blending/mix-blend-mode-isolated-group-2.html [ Failure Pass ] +crbug.com/591099 css3/blending/mix-blend-mode-isolated-group-3.html [ Failure Pass ] crbug.com/591099 css3/blending/mix-blend-mode-isolation-2-stacking-contexts.html [ Failure ] crbug.com/591099 css3/blending/mix-blend-mode-isolation-layer.html [ Failure ] -crbug.com/591099 css3/blending/mix-blend-mode-isolation-remove.html [ Failure ] +crbug.com/591099 css3/blending/mix-blend-mode-isolation-remove.html [ Failure Pass ] crbug.com/591099 css3/blending/mix-blend-mode-simple-text.html [ Failure ] -crbug.com/591099 css3/blending/mix-blend-mode-simple.html [ Failure ] -crbug.com/591099 css3/blending/mix-blend-mode-with-masking.html [ Failure ] -crbug.com/591099 css3/blending/svg-blend-color.html [ Failure ] -crbug.com/591099 css3/blending/svg-blend-hue.html [ Failure ] -crbug.com/591099 css3/blending/svg-blend-luminosity.html [ Failure ] -crbug.com/591099 css3/blending/svg-blend-multiply-alpha.html [ Failure ] -crbug.com/591099 css3/blending/svg-blend-saturation.html [ Failure ] +crbug.com/591099 css3/blending/mix-blend-mode-simple.html [ Failure Pass ] +crbug.com/591099 css3/blending/mix-blend-mode-with-masking.html [ Failure Pass ] +crbug.com/591099 css3/blending/svg-blend-color.html [ Failure Pass ] +crbug.com/591099 css3/blending/svg-blend-hue.html [ Failure Pass ] +crbug.com/591099 css3/blending/svg-blend-luminosity.html [ Failure Pass ] +crbug.com/591099 css3/blending/svg-blend-multiply-alpha.html [ Failure Pass ] +crbug.com/591099 css3/blending/svg-blend-saturation.html [ Failure Pass ] crbug.com/591099 css3/calc/catch-divide-by-0.html [ Failure ] -crbug.com/591099 css3/calc/margin.html [ Failure ] +crbug.com/591099 css3/calc/margin.html [ Failure Pass ] crbug.com/591099 css3/calc/transition-crash3.html [ Failure ] crbug.com/591099 css3/calc/transition-crash4.html [ Failure ] crbug.com/591099 css3/css3-modsel-33.html [ Failure ] @@ -1124,16 +1124,16 @@ crbug.com/591099 css3/css3-modsel-36.html [ Failure ] crbug.com/591099 css3/css3-modsel-37.html [ Failure ] crbug.com/591099 css3/filters/add-filter-rendering.html [ Failure ] -crbug.com/591099 css3/filters/blur-filter-page-scroll-parents.html [ Failure ] -crbug.com/591099 css3/filters/blur-filter-page-scroll-self.html [ Failure ] -crbug.com/591099 css3/filters/blur-filter-page-scroll.html [ Failure ] +crbug.com/591099 css3/filters/blur-filter-page-scroll-parents.html [ Failure Pass ] +crbug.com/591099 css3/filters/blur-filter-page-scroll-self.html [ Failure Pass ] +crbug.com/591099 css3/filters/blur-filter-page-scroll.html [ Failure Pass ] crbug.com/591099 css3/filters/composited-during-transition-layertree.html [ Failure ] -crbug.com/591099 css3/filters/composited-layer-bounds-after-sw-blur-animation.html [ Failure ] -crbug.com/591099 css3/filters/composited-layer-bounds-with-composited-blur.html [ Failure ] +crbug.com/591099 css3/filters/composited-layer-bounds-after-sw-blur-animation.html [ Failure Pass ] +crbug.com/591099 css3/filters/composited-layer-bounds-with-composited-blur.html [ Failure Pass ] crbug.com/591099 css3/filters/composited-layer-child-bounds-after-composited-to-sw-shadow-change.html [ Failure ] -crbug.com/591099 css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow.html [ Failure ] -crbug.com/591099 css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow.html [ Failure ] -crbug.com/591099 css3/filters/css-opacity-with-drop-shadow.html [ Failure ] +crbug.com/591099 css3/filters/composited-layer-promotion-after-outset-overlap-change-using-composited-shadow.html [ Failure Pass ] +crbug.com/591099 css3/filters/composited-layer-promotion-after-outset-overlap-change-using-sw-shadow.html [ Failure Pass ] +crbug.com/591099 css3/filters/css-opacity-with-drop-shadow.html [ Failure Pass ] crbug.com/591099 css3/filters/effect-blur-hw.html [ Failure ] crbug.com/591099 css3/filters/effect-blur.html [ Failure ] crbug.com/591099 css3/filters/effect-brightness-clamping-hw.html [ Failure ] @@ -1153,12 +1153,12 @@ crbug.com/591099 css3/filters/effect-invert.html [ Failure ] crbug.com/591099 css3/filters/effect-opacity-hw.html [ Failure ] crbug.com/591099 css3/filters/effect-opacity.html [ Failure ] -crbug.com/591099 css3/filters/effect-reference-subregion-nested.html [ Failure ] +crbug.com/591099 css3/filters/effect-reference-subregion-nested.html [ Failure Pass ] crbug.com/591099 css3/filters/effect-saturate-hw.html [ Failure ] crbug.com/591099 css3/filters/effect-saturate.html [ Failure ] crbug.com/591099 css3/filters/effect-sepia-hw.html [ Failure ] crbug.com/591099 css3/filters/effect-sepia.html [ Failure ] -crbug.com/591099 css3/filters/filtered-compositing-descendant.html [ Failure ] +crbug.com/591099 css3/filters/filtered-compositing-descendant.html [ Failure Pass ] crbug.com/591099 css3/filters/filtered-inline.html [ Failure ] crbug.com/591099 css3/filters/regions-expanding.html [ Failure ] crbug.com/591099 css3/filters/remove-filter-rendering.html [ Failure ] @@ -1190,13 +1190,13 @@ crbug.com/591099 css3/masking/clip-path-polygon-nonzero.html [ Failure ] crbug.com/591099 css3/masking/clip-path-polygon.html [ Failure ] crbug.com/591099 css3/masking/clip-path-restore.html [ Failure ] -crbug.com/591099 css3/masking/mask-luminance-gradient.html [ Failure ] -crbug.com/591099 css3/masking/mask-luminance-png.html [ Failure ] -crbug.com/591099 css3/masking/mask-luminance-svg.html [ Failure ] -crbug.com/591099 css3/masking/mask-repeat-round-content.html [ Failure ] -crbug.com/591099 css3/masking/mask-repeat-space-border.html [ Failure ] -crbug.com/591099 css3/masking/mask-repeat-space-content.html [ Failure ] -crbug.com/591099 css3/masking/mask-repeat-space-padding.html [ Failure ] +crbug.com/591099 css3/masking/mask-luminance-gradient.html [ Failure Pass ] +crbug.com/591099 css3/masking/mask-luminance-png.html [ Failure Pass ] +crbug.com/591099 css3/masking/mask-luminance-svg.html [ Failure Pass ] +crbug.com/591099 css3/masking/mask-repeat-round-content.html [ Failure Pass ] +crbug.com/591099 css3/masking/mask-repeat-space-border.html [ Failure Pass ] +crbug.com/591099 css3/masking/mask-repeat-space-content.html [ Failure Pass ] +crbug.com/591099 css3/masking/mask-repeat-space-padding.html [ Failure Pass ] crbug.com/591099 css3/selectors3/html/css3-modsel-1.html [ Failure ] crbug.com/591099 css3/selectors3/html/css3-modsel-10.html [ Failure ] crbug.com/591099 css3/selectors3/html/css3-modsel-11.html [ Failure ] @@ -1970,7 +1970,7 @@ crbug.com/591099 editing/caret/caret-color-012.html [ Crash Failure ] crbug.com/591099 editing/caret/caret-color-014.html [ Crash Failure ] crbug.com/591099 editing/caret/caret-color-015.html [ Crash Failure Timeout ] -crbug.com/591099 editing/caret/caret-color.html [ Crash Failure ] +crbug.com/591099 editing/caret/caret-color.html [ Crash Failure Timeout ] crbug.com/591099 editing/caret/caret-in-empty-cell.html [ Crash Failure Pass Timeout ] crbug.com/591099 editing/caret/caret-position.html [ Crash Failure Timeout ] crbug.com/591099 editing/deleting/4922367.html [ Failure ] @@ -1983,21 +1983,21 @@ crbug.com/591099 editing/deleting/5433862-1.html [ Failure Pass ] crbug.com/591099 editing/deleting/5433862-2.html [ Failure ] crbug.com/591099 editing/deleting/5483370.html [ Crash Failure ] -crbug.com/591099 editing/deleting/delete-3865854-fix.html [ Failure ] +crbug.com/591099 editing/deleting/delete-3865854-fix.html [ Failure Pass ] crbug.com/591099 editing/deleting/delete-at-paragraph-boundaries-011.html [ Failure Timeout ] crbug.com/591099 editing/deleting/delete-br-013.html [ Failure ] crbug.com/591099 editing/deleting/delete-empty-table.html [ Failure ] -crbug.com/591099 editing/deleting/delete-line-001.html [ Failure ] -crbug.com/591099 editing/deleting/delete-line-002.html [ Failure ] -crbug.com/591099 editing/deleting/delete-line-004.html [ Failure ] -crbug.com/591099 editing/deleting/delete-line-005.html [ Failure ] -crbug.com/591099 editing/deleting/delete-line-006.html [ Failure Timeout ] -crbug.com/591099 editing/deleting/delete-line-007.html [ Failure ] -crbug.com/591099 editing/deleting/delete-line-008.html [ Failure ] -crbug.com/591099 editing/deleting/delete-line-009.html [ Failure ] -crbug.com/591099 editing/deleting/delete-line-010.html [ Failure ] -crbug.com/591099 editing/deleting/delete-line-011.html [ Failure ] -crbug.com/591099 editing/deleting/delete-line-012.html [ Failure ] +crbug.com/591099 editing/deleting/delete-line-001.html [ Failure Pass ] +crbug.com/591099 editing/deleting/delete-line-002.html [ Failure Pass ] +crbug.com/591099 editing/deleting/delete-line-004.html [ Failure Pass ] +crbug.com/591099 editing/deleting/delete-line-005.html [ Failure Pass ] +crbug.com/591099 editing/deleting/delete-line-006.html [ Failure Pass Timeout ] +crbug.com/591099 editing/deleting/delete-line-007.html [ Failure Pass ] +crbug.com/591099 editing/deleting/delete-line-008.html [ Failure Pass ] +crbug.com/591099 editing/deleting/delete-line-009.html [ Failure Pass ] +crbug.com/591099 editing/deleting/delete-line-010.html [ Failure Pass ] +crbug.com/591099 editing/deleting/delete-line-011.html [ Failure Pass ] +crbug.com/591099 editing/deleting/delete-line-012.html [ Failure Pass ] crbug.com/591099 editing/deleting/delete-line-015.html [ Failure ] crbug.com/591099 editing/deleting/delete-line-016.html [ Failure ] crbug.com/591099 editing/deleting/delete-line-017.html [ Failure ] @@ -2239,11 +2239,11 @@ crbug.com/591099 editing/style/5084241.html [ Failure ] crbug.com/591099 editing/style/5228141.html [ Failure ] crbug.com/591099 editing/style/5279521.html [ Failure ] -crbug.com/591099 editing/style/block-style-001.html [ Failure ] -crbug.com/591099 editing/style/block-style-002.html [ Failure ] -crbug.com/591099 editing/style/block-style-003.html [ Failure ] +crbug.com/591099 editing/style/block-style-001.html [ Failure Pass ] +crbug.com/591099 editing/style/block-style-002.html [ Failure Pass ] +crbug.com/591099 editing/style/block-style-003.html [ Failure Pass ] crbug.com/591099 editing/style/block-styles-007.html [ Failure ] -crbug.com/591099 editing/style/font-family-with-space.html [ Failure ] +crbug.com/591099 editing/style/font-family-with-space.html [ Failure Pass ] crbug.com/591099 editing/style/highlight.html [ Failure ] crbug.com/591099 editing/style/remove-underline-across-paragraph-in-bold.html [ Crash Failure ] crbug.com/591099 editing/style/remove-underline-across-paragraph.html [ Crash Failure ] @@ -2458,7 +2458,6 @@ crbug.com/591099 external/wpt/css/css-ui/text-overflow-012.html [ Failure ] crbug.com/591099 external/wpt/css/css-ui/text-overflow-013.html [ Failure ] crbug.com/591099 external/wpt/css/css-ui/text-overflow-014.html [ Crash Failure ] -crbug.com/591099 external/wpt/css/css-ui/text-overflow-015.html [ Failure Pass ] crbug.com/591099 external/wpt/css/css-ui/text-overflow-022.html [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-icb-vlr-003.xht [ Pass ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-icb-vlr-005.xht [ Pass ] @@ -2785,11 +2784,11 @@ crbug.com/591099 fast/backgrounds/animated-gif-as-background.html [ Failure ] crbug.com/591099 fast/backgrounds/animated-svg-as-mask.html [ Failure ] crbug.com/591099 fast/backgrounds/background-clip-text.html [ Failure ] -crbug.com/591099 fast/backgrounds/background-color-image-border-radius-bleed.html [ Failure ] +crbug.com/591099 fast/backgrounds/background-color-image-border-radius-bleed.html [ Failure Pass ] crbug.com/591099 fast/backgrounds/background-inherit-color-bug.html [ Failure ] crbug.com/591099 fast/backgrounds/background-leakage-transforms.html [ Failure ] crbug.com/591099 fast/backgrounds/background-leakage.html [ Failure ] -crbug.com/591099 fast/backgrounds/background-multi-image-border-radius-bleed.html [ Failure ] +crbug.com/591099 fast/backgrounds/background-multi-image-border-radius-bleed.html [ Failure Pass ] crbug.com/591099 fast/backgrounds/background-origin-root-element.html [ Failure ] crbug.com/591099 fast/backgrounds/background-position-1.html [ Failure ] crbug.com/591099 fast/backgrounds/background-position-parsing.html [ Failure ] @@ -2797,13 +2796,13 @@ crbug.com/591099 fast/backgrounds/background-repeat-with-background-color.html [ Failure ] crbug.com/591099 fast/backgrounds/background-svg-scaling-zoom.html [ Failure ] crbug.com/591099 fast/backgrounds/background-svg-scaling.html [ Failure ] -crbug.com/591099 fast/backgrounds/background-with-sub-pixel-offset-positioning.html [ Failure ] +crbug.com/591099 fast/backgrounds/background-with-sub-pixel-offset-positioning.html [ Failure Pass ] crbug.com/591099 fast/backgrounds/body-generated-image-propagated-to-root.html [ Failure ] crbug.com/591099 fast/backgrounds/border-radius-split-background-image.html [ Crash Failure ] crbug.com/591099 fast/backgrounds/border-radius-split-background.html [ Failure ] -crbug.com/591099 fast/backgrounds/gradient-background-leakage-2.html [ Failure ] -crbug.com/591099 fast/backgrounds/gradient-background-leakage-hidpi.html [ Failure ] -crbug.com/591099 fast/backgrounds/gradient-background-leakage.html [ Failure ] +crbug.com/591099 fast/backgrounds/gradient-background-leakage-2.html [ Failure Pass ] +crbug.com/591099 fast/backgrounds/gradient-background-leakage-hidpi.html [ Failure Pass ] +crbug.com/591099 fast/backgrounds/gradient-background-leakage.html [ Failure Pass ] crbug.com/591099 fast/backgrounds/mask-box-image.html [ Failure ] crbug.com/591099 fast/backgrounds/mask-composite.html [ Failure ] crbug.com/591099 fast/backgrounds/opacity-on-document-element.html [ Failure ] @@ -2838,7 +2837,7 @@ crbug.com/591099 fast/backgrounds/size/backgroundSize22.html [ Failure ] crbug.com/591099 fast/backgrounds/size/contain-and-cover-zoomed.html [ Failure ] crbug.com/591099 fast/backgrounds/size/contain-and-cover.html [ Failure ] -crbug.com/591099 fast/backgrounds/size/scaled-sprited-background.html [ Failure ] +crbug.com/591099 fast/backgrounds/size/scaled-sprited-background.html [ Failure Pass ] crbug.com/591099 fast/backgrounds/size/zero.html [ Failure ] crbug.com/591099 fast/backgrounds/svg-as-mask.html [ Failure ] crbug.com/591099 fast/block/basic/011.html [ Failure ] @@ -2888,7 +2887,7 @@ crbug.com/591099 fast/block/float/rubybase-children-moved-crash-2.html [ Crash Failure ] crbug.com/591099 fast/block/float/selection-gap-clip-out-tiger-crash.html [ Failure ] crbug.com/591099 fast/block/float/trailing-float-with-columns.html [ Failure ] -crbug.com/591099 fast/block/inflow-bottom-margin.html [ Failure ] +crbug.com/591099 fast/block/inflow-bottom-margin.html [ Failure Pass ] crbug.com/591099 fast/block/inline-children-root-linebox-crash.html [ Failure ] crbug.com/591099 fast/block/line-layout/floats-do-not-fit-on-line.html [ Failure ] crbug.com/591099 fast/block/margin-collapse/103.html [ Failure ] @@ -2898,7 +2897,7 @@ crbug.com/591099 fast/block/margin-collapse/webkit-margin-collapse-siblings.html [ Failure ] crbug.com/591099 fast/block/margin-left-margin-right-auto.html [ Failure ] crbug.com/591099 fast/block/over-constrained-auto-margin.html [ Failure ] -crbug.com/591099 fast/block/positioned-bottom-margin.html [ Failure ] +crbug.com/591099 fast/block/positioned-bottom-margin.html [ Failure Pass ] crbug.com/591099 fast/block/positioning/056.html [ Failure ] crbug.com/591099 fast/block/positioning/059.html [ Failure ] crbug.com/591099 fast/block/positioning/061.html [ Failure ] @@ -3025,7 +3024,7 @@ crbug.com/591099 fast/borders/inline-mask-overlay-image-outset.html [ Failure ] crbug.com/591099 fast/borders/inline-mask-overlay-image.html [ Failure ] crbug.com/591099 fast/borders/outline-alpha-inline.html [ Failure ] -crbug.com/591099 fast/borders/overflow-hidden-border-radius-force-backing-store.html [ Failure ] +crbug.com/591099 fast/borders/overflow-hidden-border-radius-force-backing-store.html [ Failure Pass ] crbug.com/591099 fast/borders/rtl-border-01.html [ Failure ] crbug.com/591099 fast/borders/rtl-border-02.html [ Failure ] crbug.com/591099 fast/borders/rtl-border-03.html [ Failure ] @@ -3036,26 +3035,26 @@ crbug.com/591099 fast/box-shadow/border-radius-big.html [ Failure ] crbug.com/591099 fast/box-shadow/box-shadow-radius.html [ Failure ] crbug.com/591099 fast/box-shadow/box-shadow-transformed.html [ Failure ] -crbug.com/591099 fast/box-shadow/box-shadow-with-zero-radius.html [ Failure ] +crbug.com/591099 fast/box-shadow/box-shadow-with-zero-radius.html [ Failure Pass ] crbug.com/591099 fast/box-shadow/box-shadow.html [ Failure ] crbug.com/591099 fast/box-shadow/inset-box-shadow-radius.html [ Failure ] crbug.com/591099 fast/box-shadow/inset-box-shadows.html [ Failure ] -crbug.com/591099 fast/box-shadow/inset-shadow-large-offset.html [ Failure ] +crbug.com/591099 fast/box-shadow/inset-shadow-large-offset.html [ Failure Pass ] crbug.com/591099 fast/box-shadow/inset-subpixel.html [ Failure ] crbug.com/591099 fast/box-shadow/inset-with-extraordinary-radii-and-border.html [ Failure ] crbug.com/591099 fast/box-shadow/inset.html [ Failure ] crbug.com/591099 fast/box-shadow/scaled-box-shadow.html [ Failure ] -crbug.com/591099 fast/box-shadow/shadow-buffer-partial.html [ Failure ] -crbug.com/591099 fast/box-shadow/shadow-tiling-artifact.html [ Failure ] -crbug.com/591099 fast/box-shadow/single-pixel-shadow.html [ Failure ] +crbug.com/591099 fast/box-shadow/shadow-buffer-partial.html [ Failure Pass ] +crbug.com/591099 fast/box-shadow/shadow-tiling-artifact.html [ Failure Pass ] +crbug.com/591099 fast/box-shadow/single-pixel-shadow.html [ Failure Pass ] crbug.com/591099 fast/box-shadow/spread.html [ Failure ] crbug.com/591099 fast/box-shadow/transform-fringing.html [ Failure ] crbug.com/591099 fast/canvas-api/toDataURL-supportedTypes.html [ Failure ] crbug.com/591099 fast/canvas/canvas-createImageBitmap-drawImage.html [ Timeout ] crbug.com/591099 fast/canvas/canvas-drawImage-animated-images.html [ Failure ] -crbug.com/591099 fast/canvas/canvas-ellipse-connecting-line.html [ Failure ] +crbug.com/591099 fast/canvas/canvas-ellipse-connecting-line.html [ Failure Pass ] crbug.com/591099 fast/canvas/canvas-measure-bidi-text.html [ Failure ] -crbug.com/591099 fast/canvas/canvas-render-layer.html [ Failure ] +crbug.com/591099 fast/canvas/canvas-render-layer.html [ Failure Pass ] crbug.com/591099 fast/canvas/canvas-shadow-source-in.html [ Failure ] crbug.com/591099 fast/canvas/canvas-transforms-during-path.html [ Failure ] crbug.com/591099 fast/canvas/fill-stroke-clip-reset-path.html [ Failure ] @@ -3426,7 +3425,7 @@ crbug.com/591099 fast/css/outline-narrowLine.html [ Failure ] crbug.com/591099 fast/css/overflow-rtl-border-after.html [ Failure ] crbug.com/591099 fast/css/padding-margin-negative-border.html [ Crash Pass ] -crbug.com/591099 fast/css/pending-stylesheet-repaint.html [ Failure ] +crbug.com/591099 fast/css/pending-stylesheet-repaint.html [ Failure Pass ] crbug.com/591099 fast/css/pendingStylesheetFontSize.html [ Failure ] crbug.com/591099 fast/css/percent-min-width-img-src-change.html [ Failure Pass ] crbug.com/591099 fast/css/percent-top-relative-container-height-unspecified.html [ Failure ] @@ -3467,11 +3466,11 @@ crbug.com/591099 fast/css/selector-set-attribute.html [ Failure ] crbug.com/591099 fast/css/shadow-multiple.html [ Failure ] crbug.com/591099 fast/css/simple-selector-chain-parsing.html [ Failure ] -crbug.com/591099 fast/css/square-button-appearance.html [ Failure ] +crbug.com/591099 fast/css/square-button-appearance.html [ Failure Pass ] crbug.com/591099 fast/css/sticky/sticky-top-overflow-scroll-by-fragment.html [ Failure ] crbug.com/591099 fast/css/style-outside-head.html [ Failure ] crbug.com/591099 fast/css/style-parsed-outside-head.html [ Failure ] -crbug.com/591099 fast/css/style-tag-display-none.html [ Failure ] +crbug.com/591099 fast/css/style-tag-display-none.html [ Failure Pass ] crbug.com/591099 fast/css/table-text-align-quirk.html [ Failure ] crbug.com/591099 fast/css/table-text-align-strict.html [ Failure ] crbug.com/591099 fast/css/text-align.html [ Failure ] @@ -3634,7 +3633,7 @@ crbug.com/591099 fast/dynamic/005.html [ Failure ] crbug.com/591099 fast/dynamic/006.html [ Crash Failure ] crbug.com/591099 fast/dynamic/007.html [ Failure ] -crbug.com/591099 fast/dynamic/008.html [ Failure ] +crbug.com/591099 fast/dynamic/008.html [ Failure Pass ] crbug.com/591099 fast/dynamic/009.html [ Failure ] crbug.com/591099 fast/dynamic/010.html [ Failure ] crbug.com/591099 fast/dynamic/011.html [ Failure ] @@ -3673,8 +3672,8 @@ crbug.com/591099 fast/dynamic/positioned-movement-with-positioned-children.html [ Failure ] crbug.com/591099 fast/dynamic/selection-highlight-adjust.html [ Failure ] crbug.com/591099 fast/dynamic/staticY-marking-parents-regression.html [ Failure ] -crbug.com/591099 fast/dynamic/staticY.html [ Failure ] -crbug.com/591099 fast/dynamic/subtree-boundary-percent-height.html [ Failure ] +crbug.com/591099 fast/dynamic/staticY.html [ Failure Pass ] +crbug.com/591099 fast/dynamic/subtree-boundary-percent-height.html [ Failure Pass ] crbug.com/591099 fast/dynamic/subtree-no-common-root-static-y.html [ Failure ] crbug.com/591099 fast/dynamic/subtree-parent-static-y.html [ Failure ] crbug.com/591099 fast/dynamic/subtree-table-cell-height.html [ Failure ] @@ -3870,7 +3869,7 @@ crbug.com/591099 fast/forms/month/month-appearance-pseudo-elements.html [ Failure ] crbug.com/591099 fast/forms/negativeLineHeight.html [ Failure ] crbug.com/591099 fast/forms/number/number-appearance-datalist.html [ Failure ] -crbug.com/591099 fast/forms/number/number-appearance-rtl.html [ Failure ] +crbug.com/591099 fast/forms/number/number-appearance-rtl.html [ Failure Pass ] crbug.com/591099 fast/forms/number/number-appearance-spinbutton-disabled-readonly.html [ Failure ] crbug.com/591099 fast/forms/number/number-appearance-spinbutton-layer.html [ Failure ] crbug.com/591099 fast/forms/number/number-spinbutton-click-in-iframe.html [ Failure ] @@ -4045,7 +4044,7 @@ crbug.com/591099 fast/forms/text/input-readonly-dimmed.html [ Failure ] crbug.com/591099 fast/forms/text/input-readonly-empty.html [ Failure ] crbug.com/591099 fast/forms/text/input-spaces.html [ Failure ] -crbug.com/591099 fast/forms/text/input-tab-shows-caret.html [ Failure ] +crbug.com/591099 fast/forms/text/input-tab-shows-caret.html [ Failure Pass ] crbug.com/591099 fast/forms/text/input-table.html [ Failure ] crbug.com/591099 fast/forms/text/input-text-click-inside.html [ Failure ] crbug.com/591099 fast/forms/text/input-text-click-outside.html [ Failure ] @@ -4062,7 +4061,7 @@ crbug.com/591099 fast/forms/text/text-reset.html [ Failure ] crbug.com/591099 fast/forms/text/textfield-focus-ring.html [ Failure ] crbug.com/591099 fast/forms/text/textfield-outline.html [ Failure ] -crbug.com/591099 fast/forms/text/textfield-overflow-by-value-update.html [ Failure ] +crbug.com/591099 fast/forms/text/textfield-overflow-by-value-update.html [ Failure Pass ] crbug.com/591099 fast/forms/text/textfield-overflow.html [ Failure ] crbug.com/591099 fast/forms/textarea/basic-textareas-quirks.html [ Failure ] crbug.com/591099 fast/forms/textarea/basic-textareas.html [ Failure ] @@ -4118,7 +4117,7 @@ crbug.com/591099 fast/frames/frame-set-scaling-rotate.html [ Failure ] crbug.com/591099 fast/frames/frame-set-scaling-skew.html [ Failure ] crbug.com/591099 fast/frames/frame-set-scaling.html [ Failure ] -crbug.com/591099 fast/frames/frame-set-whitespace-attributes.html [ Failure ] +crbug.com/591099 fast/frames/frame-set-whitespace-attributes.html [ Failure Pass ] crbug.com/591099 fast/frames/frameElement-frame.html [ Failure ] crbug.com/591099 fast/frames/frameElement-iframe.html [ Failure ] crbug.com/591099 fast/frames/frameset-frameborder-boolean-values.html [ Failure ] @@ -4134,7 +4133,7 @@ crbug.com/591099 fast/frames/invalid.html [ Failure ] crbug.com/591099 fast/frames/no-frame-borders.html [ Failure ] crbug.com/591099 fast/frames/onlyCommentInIFrame.html [ Failure ] -crbug.com/591099 fast/frames/paint-iframe-background.html [ Failure ] +crbug.com/591099 fast/frames/paint-iframe-background.html [ Failure Pass ] crbug.com/591099 fast/frames/sandboxed-iframe-forms-dynamic.html [ Failure ] crbug.com/591099 fast/frames/sandboxed-iframe-forms.html [ Failure ] crbug.com/591099 fast/frames/sandboxed-iframe-navigation-allowed.html [ Failure ] @@ -4176,9 +4175,9 @@ crbug.com/591099 fast/gradients/unprefixed-radial-gradients2.html [ Failure ] crbug.com/591099 fast/gradients/unprefixed-repeating-linear-gradient.html [ Failure ] crbug.com/591099 fast/gradients/unprefixed-repeating-radial-gradients.html [ Failure ] -crbug.com/591099 fast/gradients/zero-range-repeating-gradient-hang.html [ Failure ] +crbug.com/591099 fast/gradients/zero-range-repeating-gradient-hang.html [ Failure Pass ] crbug.com/591099 fast/harness/hello_again.html [ Failure ] -crbug.com/591099 fast/hidpi/image-set-list-style-image.html [ Failure ] +crbug.com/591099 fast/hidpi/image-set-list-style-image.html [ Crash Failure ] crbug.com/591099 fast/hidpi/image-set-shape-outside.html [ Failure ] crbug.com/591099 fast/hidpi/image-srcset-intrinsic-size.html [ Failure ] crbug.com/591099 fast/history/saves-state-after-frame-nav.html [ Failure ] @@ -4257,12 +4256,12 @@ crbug.com/591099 fast/layers/nested-layers-1.html [ Failure ] crbug.com/591099 fast/layers/normal-flow-hit-test.html [ Failure ] crbug.com/591099 fast/layers/opacity-outline.html [ Failure ] -crbug.com/591099 fast/layers/opacity-stacking.html [ Failure ] +crbug.com/591099 fast/layers/opacity-stacking.html [ Failure Pass ] crbug.com/591099 fast/layers/opacity-transforms.html [ Failure ] crbug.com/591099 fast/layers/overflow-hidden-rounded-corners-occlusion.html [ Failure ] crbug.com/591099 fast/layers/overflow-scroll-auto-switch.html [ Failure ] crbug.com/591099 fast/layers/perspective-inline-no-display.html [ Failure ] -crbug.com/591099 fast/layers/positioned-inside-root-with-margins.html [ Failure ] +crbug.com/591099 fast/layers/positioned-inside-root-with-margins.html [ Failure Pass ] crbug.com/591099 fast/layers/remove-layer-with-nested-stacking.html [ Failure ] crbug.com/591099 fast/layers/remove-only-this-layer-update.html [ Failure ] crbug.com/591099 fast/layers/scroll-rect-to-visible.html [ Failure ] @@ -4325,9 +4324,6 @@ crbug.com/591099 fast/multicol/anonymous-block-split-crash.html [ Crash ] crbug.com/591099 fast/multicol/balance-break-inside-avoid.html [ Failure ] crbug.com/591099 fast/multicol/balance-breakafter-before-nested-block.html [ Failure ] -crbug.com/591099 fast/multicol/balance-fixed-height-unused-space-after-strutless-break.html [ Failure ] -crbug.com/591099 fast/multicol/balance-fixed-height-unused-space-nested-block.html [ Failure ] -crbug.com/591099 fast/multicol/balance-fixed-height-unused-space.html [ Failure ] crbug.com/591099 fast/multicol/balance-float-after-forced-break.html [ Failure ] crbug.com/591099 fast/multicol/balance-float-in-inline.html [ Failure ] crbug.com/591099 fast/multicol/balance-float-with-margin-top-and-line-after-break-2.html [ Failure ] @@ -4365,7 +4361,6 @@ crbug.com/591099 fast/multicol/column-rules.html [ Failure ] crbug.com/591099 fast/multicol/columns-shorthand-parsing.html [ Failure ] crbug.com/591099 fast/multicol/composited-inner-multicol.html [ Failure ] -crbug.com/591099 fast/multicol/composited-layer-multiple-fragments-translated.html [ Failure ] crbug.com/591099 fast/multicol/composited-layer.html [ Failure ] crbug.com/591099 fast/multicol/composited-opacity-2nd-and-3rd-column.html [ Crash Failure ] crbug.com/591099 fast/multicol/composited-relpos-clipped.html [ Crash Failure ] @@ -4392,6 +4387,7 @@ crbug.com/591099 fast/multicol/dynamic/insert-block-between-spanners.html [ Failure ] crbug.com/591099 fast/multicol/dynamic/insert-block-into-content.html [ Failure ] crbug.com/591099 fast/multicol/dynamic/insert-block-into-inline-beside-ex-spanner-table-column.html [ Crash ] +crbug.com/591099 fast/multicol/dynamic/insert-block-into-spanner.html [ Failure ] crbug.com/591099 fast/multicol/dynamic/insert-float-after-content-in-spanner.html [ Failure Pass ] crbug.com/591099 fast/multicol/dynamic/insert-float-before-content-in-spanner.html [ Failure Pass ] crbug.com/591099 fast/multicol/dynamic/insert-spanner-after-abspos-subtree-crash.html [ Crash ] @@ -4424,6 +4420,7 @@ crbug.com/591099 fast/multicol/dynamic/remove-block-from-content-between-spanners.html [ Failure ] crbug.com/591099 fast/multicol/dynamic/remove-column-content-next-to-abspos-between-spanners.html [ Failure ] crbug.com/591099 fast/multicol/dynamic/remove-spanner-after-content.html [ Failure ] +crbug.com/591099 fast/multicol/dynamic/remove-spanner-before-content.html [ Failure ] crbug.com/591099 fast/multicol/dynamic/remove-spanner-in-content.html [ Failure ] crbug.com/591099 fast/multicol/dynamic/remove-spanner-in-empty-nested-block-crash.html [ Crash ] crbug.com/591099 fast/multicol/dynamic/spanner-after-content-becomes-regular-block.html [ Failure ] @@ -4527,7 +4524,6 @@ crbug.com/591099 fast/multicol/nested-with-tall-block.html [ Failure ] crbug.com/591099 fast/multicol/newmulticol/avoid-column-break-inside.html [ Failure ] crbug.com/591099 fast/multicol/newmulticol/balance-images.html [ Failure ] -crbug.com/591099 fast/multicol/newmulticol/balance-maxheight2.html [ Failure ] crbug.com/591099 fast/multicol/newmulticol/balance10.html [ Failure ] crbug.com/591099 fast/multicol/newmulticol/balance2.html [ Failure ] crbug.com/591099 fast/multicol/newmulticol/balance3.html [ Failure ] @@ -4564,9 +4560,11 @@ crbug.com/591099 fast/multicol/overflow-content.html [ Failure ] crbug.com/591099 fast/multicol/overflow-unsplittable.html [ Failure ] crbug.com/591099 fast/multicol/paged-becomes-multicol-with-spanner.html [ Crash ] +crbug.com/591099 fast/multicol/pageLogicalOffset-vertical.html [ Failure ] crbug.com/591099 fast/multicol/paginate-block-replaced.html [ Failure ] crbug.com/591099 fast/multicol/positioned-outside-of-columns.html [ Failure ] crbug.com/591099 fast/multicol/positioned-split.html [ Failure ] +crbug.com/591099 fast/multicol/positioned-with-constrained-height.html [ Failure ] crbug.com/591099 fast/multicol/positive-leading.html [ Failure ] crbug.com/591099 fast/multicol/pushed-line-affected-by-float.html [ Failure ] crbug.com/591099 fast/multicol/relayout-and-push-float.html [ Failure ] @@ -4613,6 +4611,7 @@ crbug.com/591099 fast/multicol/span/inside-block-with-fixed-height-crash.html [ Crash ] crbug.com/591099 fast/multicol/span/inside-block-with-fixed-height.html [ Crash ] crbug.com/591099 fast/multicol/span/invalid-spanner-in-abspos.html [ Crash Failure ] +crbug.com/591099 fast/multicol/span/invalid-spanner-in-transform.html [ Failure ] crbug.com/591099 fast/multicol/span/margin-on-multicol.html [ Failure ] crbug.com/591099 fast/multicol/span/multicol-with-padding.html [ Failure ] crbug.com/591099 fast/multicol/span/multicol-with-spanner-becomes-regular-block.html [ Crash ] @@ -4855,23 +4854,23 @@ crbug.com/714962 compositing/gestures/gesture-tapHighlight-with-squashing.html [ Crash ] crbug.com/714962 compositing/images/direct-image-clip-path.html [ Failure ] crbug.com/714962 compositing/images/direct-image-dynamic-clip-path.html [ Failure ] -crbug.com/714962 compositing/overflow/absolute-element-in-isolated-composited-ancestor.html [ Failure ] +crbug.com/714962 compositing/overflow/absolute-element-in-isolated-composited-ancestor.html [ Failure Pass ] crbug.com/591099 compositing/overflow/border-radius-above-composited-subframe.html [ Failure ] crbug.com/591099 compositing/overflow/border-radius-composited-subframe.html [ Failure ] crbug.com/591099 compositing/overflow/border-radius-on-squashed-layers.html [ Failure Pass ] crbug.com/591099 compositing/overflow/composited-scroll-with-fractional-translation.html [ Pass ] crbug.com/591099 compositing/overflow/do-not-crash-use-after-free-update-widget-positions.html [ Crash ] -crbug.com/714962 compositing/overflow/fixed-element-in-isolated-composited-ancestor.html [ Failure ] +crbug.com/714962 compositing/overflow/fixed-element-in-isolated-composited-ancestor.html [ Failure Pass ] crbug.com/591099 compositing/overflow/get-transform-from-non-box-container.html [ Crash ] crbug.com/714962 compositing/overflow/image-load-overflow-scrollbars.html [ Failure ] -crbug.com/714962 compositing/overflow/mixed-composited-nested-sticky-overflow-scroller.html [ Failure ] +crbug.com/714962 compositing/overflow/mixed-composited-nested-sticky-overflow-scroller.html [ Failure Pass ] crbug.com/591099 compositing/overflow/overflow-with-negative-z-index-child.html [ Failure ] crbug.com/714962 compositing/overflow/rtl-overflow.html [ Failure ] -crbug.com/591099 compositing/perspective-interest-rect.html [ Failure ] +crbug.com/591099 compositing/perspective-interest-rect.html [ Failure Pass ] crbug.com/714962 compositing/squashing/squash-composited-input.html [ Failure Pass ] crbug.com/714962 compositing/squashing/squash-overflow-hidden-scrolltop.html [ Failure ] crbug.com/591099 compositing/squashing/squashing-does-not-stop-transform-propagation.html [ Crash Pass ] -crbug.com/714962 compositing/squashing/universal-accelerated-overflow-scrolling.html [ Failure ] +crbug.com/714962 compositing/squashing/universal-accelerated-overflow-scrolling.html [ Failure Pass ] crbug.com/714962 compositing/transitions/transform-on-large-layer.html [ Failure ] crbug.com/591099 compositing/will-change/will-change-preserve-backface-visibility.html [ Crash Pass ] crbug.com/591099 compositing/z-order/collect-layers-does-not-initialize-pos-z-order-list.html [ Crash ] @@ -4922,7 +4921,7 @@ crbug.com/714962 css3/masking/mask-composite-missing-image.html [ Failure ] crbug.com/714962 css3/tab-size-complex-path.html [ Failure ] crbug.com/714962 css3/tab-size.html [ Failure ] -crbug.com/591099 editing/caret/caret-painting-low-dpi.html [ Failure ] +crbug.com/591099 editing/caret/caret-painting-low-dpi.html [ Failure Pass ] crbug.com/714962 editing/caret/in-multicol-child.html [ Failure ] crbug.com/714962 editing/deleting/4916235-1.html [ Failure ] crbug.com/714962 editing/deleting/delete-across-editable-content-boundaries-2.html [ Crash ] @@ -5017,13 +5016,14 @@ crbug.com/714962 external/wpt/css/css-backgrounds/background-image-006.html [ Failure Pass ] crbug.com/714962 external/wpt/css/css-backgrounds/background-size/background-size-cover.xht [ Failure ] crbug.com/714962 external/wpt/css/css-backgrounds/css3-background-clip.html [ Failure ] +crbug.com/591099 external/wpt/css/css-backgrounds/scroll-positioned-multiple-background-images.html [ Failure Pass ] crbug.com/714962 external/wpt/css/css-display/display-contents-dynamic-before-after-001.html [ Failure ] crbug.com/714962 external/wpt/css/css-display/display-contents-dynamic-before-after-first-letter-001.html [ Failure ] crbug.com/591099 external/wpt/css/css-display/display-contents-dynamic-table-002-none.html [ Crash ] -crbug.com/591099 external/wpt/css/css-display/display-contents-replaced-001.html [ Crash ] +crbug.com/591099 external/wpt/css/css-display/display-contents-replaced-001.html [ Crash Pass ] crbug.com/591099 external/wpt/css/css-display/display-contents-text-inherit.html [ Pass ] -crbug.com/591099 external/wpt/css/css-flexbox/flexbox_columns-flexitems-2.html [ Failure ] -crbug.com/591099 external/wpt/css/css-flexbox/flexbox_columns-flexitems.html [ Failure ] +crbug.com/591099 external/wpt/css/css-flexbox/flexbox_columns-flexitems-2.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-flexbox/flexbox_columns-flexitems.html [ Failure Pass ] crbug.com/591099 external/wpt/css/css-flexbox/percentage-heights-003.html [ Pass ] crbug.com/714962 external/wpt/css/css-flexbox/position-absolute-005.html [ Failure ] crbug.com/714962 external/wpt/css/css-fonts/font-display/font-display.html [ Failure ] @@ -5036,23 +5036,25 @@ crbug.com/591099 external/wpt/css/css-fonts/matching/fixed-stretch-style-over-weight.html [ Pass ] crbug.com/591099 external/wpt/css/css-fonts/test_font_family_parsing.html [ Timeout ] crbug.com/714962 external/wpt/css/css-grid/abspos/grid-positioned-children-writing-modes-001.html [ Failure ] -crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-002.html [ Failure ] -crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-005.html [ Failure ] -crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-006.html [ Failure ] -crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-008.html [ Failure ] +crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-002.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-005.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-006.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-008.html [ Failure Pass ] crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-009.html [ Failure ] crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-010.html [ Failure ] crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-011.html [ Failure ] -crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-012.html [ Failure ] -crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-001.html [ Failure ] -crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-004.html [ Failure ] -crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-005.html [ Failure ] -crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-006.html [ Failure ] -crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-009.html [ Failure ] -crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-010.html [ Failure ] -crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-012.html [ Failure ] -crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-015.html [ Failure ] -crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-016.html [ Failure ] +crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-012.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-001.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-004.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-005.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-006.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-009.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-010.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-012.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-015.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-016.html [ Failure Pass ] +crbug.com/591099 external/wpt/css/css-grid/grid-model/grid-container-ignores-first-letter-001.html [ Pass ] +crbug.com/591099 external/wpt/css/css-grid/grid-model/grid-container-ignores-first-line-001.html [ Pass ] crbug.com/591099 external/wpt/css/css-multicol/multicol-basic-001.html [ Failure ] crbug.com/591099 external/wpt/css/css-multicol/multicol-basic-002.html [ Failure ] crbug.com/591099 external/wpt/css/css-multicol/multicol-basic-003.html [ Failure ] @@ -5177,7 +5179,7 @@ crbug.com/591099 external/wpt/css/css-position/position-sticky-nested-inline.html [ Crash ] crbug.com/714962 external/wpt/css/css-scroll-anchoring/start-edge-in-block-layout-direction.html [ Failure ] crbug.com/714962 external/wpt/css/css-scroll-anchoring/wrapped-text.html [ Failure ] -crbug.com/591099 external/wpt/css/css-style-attr/style-attr-urls-001.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-style-attr/style-attr-urls-001.xht [ Failure Pass ] crbug.com/591099 external/wpt/css/css-style-attr/style-attr-urls-002.xht [ Failure ] crbug.com/714962 external/wpt/css/css-tables/visibility-collapse-colspan-003.html [ Failure ] crbug.com/591099 external/wpt/css/css-text-decor/text-emphasis-position-above-left-001.xht [ Crash Failure ] @@ -5206,6 +5208,7 @@ crbug.com/714962 external/wpt/css/css-ui/outline-004.html [ Failure ] crbug.com/714962 external/wpt/css/css-ui/text-overflow-001.html [ Failure ] crbug.com/714962 external/wpt/css/css-ui/text-overflow-003.html [ Failure ] +crbug.com/591099 external/wpt/css/css-ui/text-overflow-006.html [ Pass ] crbug.com/714962 external/wpt/css/css-ui/text-overflow-008.html [ Crash Failure ] crbug.com/714962 external/wpt/css/css-ui/text-overflow-009.html [ Failure ] crbug.com/591099 external/wpt/css/css-ui/text-overflow-010.html [ Pass ] @@ -5226,13 +5229,13 @@ crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-021.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-023.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-025.xht [ Failure ] -crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-027.xht [ Failure ] +crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-027.xht [ Failure Pass ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-029.xht [ Failure Pass ] -crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-031.xht [ Failure ] +crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-031.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-033.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-035.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-037.xht [ Failure ] -crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-039.xht [ Failure ] +crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-039.xht [ Failure Pass ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-041.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-043.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-045.xht [ Failure Pass ] @@ -5290,9 +5293,9 @@ crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-153.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-155.xht [ Failure Pass ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-157.xht [ Failure Pass ] -crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-159.xht [ Failure ] +crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-159.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-161.xht [ Failure Pass ] -crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-163.xht [ Failure ] +crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-163.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-165.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-167.xht [ Failure Pass ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-169.xht [ Failure Pass ] @@ -5318,11 +5321,11 @@ crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-209.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-211.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-213.xht [ Failure Pass ] -crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-215.xht [ Failure ] +crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-215.xht [ Failure Pass ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-217.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-219.xht [ Failure ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-221.xht [ Failure Pass ] -crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-223.xht [ Failure ] +crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-223.xht [ Failure Pass ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-225.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-227.xht [ Failure Pass ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vlr-229.xht [ Failure Pass ] @@ -5354,9 +5357,9 @@ crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-052.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-054.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-056.xht [ Failure ] -crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-058.xht [ Failure ] +crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-058.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-060.xht [ Failure ] -crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-062.xht [ Failure ] +crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-062.xht [ Failure Pass ] crbug.com/591099 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-064.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-066.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/abs-pos-non-replaced-vrl-068.xht [ Failure ] @@ -5453,7 +5456,7 @@ crbug.com/714962 external/wpt/css/css-writing-modes/direction-vrl-002.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/direction-vrl-004.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/float-shrink-to-fit-vrl-008.xht [ Failure ] -crbug.com/714962 external/wpt/css/css-writing-modes/float-vlr-005.xht [ Failure ] +crbug.com/714962 external/wpt/css/css-writing-modes/float-vlr-005.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/float-vlr-007.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/float-vrl-008.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/inline-block-alignment-002.xht [ Failure ] @@ -5508,12 +5511,12 @@ crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-013.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-015.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-017.xht [ Failure Pass ] -crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-019.xht [ Failure ] +crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vlr-019.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vrl-002.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vrl-004.xht [ Failure ] crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vrl-006.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vrl-008.xht [ Failure Pass ] -crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vrl-010.xht [ Failure ] +crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vrl-010.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vrl-012.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vrl-014.xht [ Failure Pass ] crbug.com/714962 external/wpt/css/css-writing-modes/text-align-vrl-016.xht [ Failure Pass ] @@ -5587,6 +5590,7 @@ crbug.com/591099 external/wpt/encoding/legacy-mb-japanese/iso-2022-jp/iso2022jp-encode-href.html [ Timeout ] crbug.com/591099 external/wpt/feature-policy/autoplay-allowed-by-feature-policy-attribute.https.sub.html [ Failure ] crbug.com/591099 external/wpt/feature-policy/autoplay-allowed-by-feature-policy.https.sub.html [ Failure ] +crbug.com/591099 external/wpt/html/dom/documents/dom-tree-accessors/Document.currentScript.html [ Pass ] crbug.com/591099 external/wpt/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-newelements-xhtml.xhtml [ Crash ] crbug.com/591099 external/wpt/html/dom/documents/dom-tree-accessors/document.getElementsByName/document.getElementsByName-newelements.html [ Crash ] crbug.com/591099 external/wpt/html/dom/documents/resource-metadata-management/document-lastModified-01.html [ Pass ] @@ -5644,12 +5648,12 @@ crbug.com/591099 external/wpt/webrtc/interfaces.https.html [ Pass Timeout ] crbug.com/591099 external/wpt/websockets/cookies/005.html [ Pass ] crbug.com/591099 external/wpt/websockets/cookies/007.html [ Failure Pass ] +crbug.com/591099 external/wpt/websockets/opening-handshake/005.html [ Pass ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/class_object/class_white-space_pre-wrap_wrapped.html [ Crash ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/italic_object/italic_white-space_pre-wrap_wrapped.html [ Crash ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/underline_object/underline_white-space_pre-wrap_wrapped.html [ Crash ] crbug.com/591099 external/wpt/webvtt/rendering/cues-with-video/processing-model/selectors/cue_function/voice_object/voice_white-space_pre-wrap_wrapped.html [ Crash ] crbug.com/714962 fast/backgrounds/root-background-propagation3.html [ Failure ] -crbug.com/714962 fast/backgrounds/selection-background-color.html [ Failure Pass ] crbug.com/714962 fast/block/basic/015.html [ Failure ] crbug.com/714962 fast/block/basic/016.html [ Failure ] crbug.com/591099 fast/block/block-remove-child-delete-line-box-crash.html [ Crash ] @@ -5682,7 +5686,6 @@ crbug.com/714962 fast/block/margin-collapse/044.html [ Failure ] crbug.com/714962 fast/block/margin-collapse/line-beside-float-complex-margin-collapsing.html [ Failure ] crbug.com/591099 fast/block/percent-height-descendant-not-removed-crash2.html [ Crash ] -crbug.com/591099 fast/block/positioning/052.html [ Crash Pass ] crbug.com/591099 fast/block/positioning/058.html [ Crash Pass ] crbug.com/591099 fast/block/positioning/abspositioned-object-under-split-relpositioned-inline-crash.html [ Crash ] crbug.com/714962 fast/block/positioning/auto/vertical-rl/006.html [ Failure ] @@ -5725,7 +5728,7 @@ crbug.com/714962 fast/canvas/canvas-text-ideographic-space.html [ Failure ] crbug.com/714962 fast/canvas/canvas-textMetrics-width.html [ Failure ] crbug.com/714962 fast/canvas/image-object-in-canvas.html [ Failure ] -crbug.com/714962 fast/canvas/setWidthResetAfterForcedRender.html [ Failure ] +crbug.com/714962 fast/canvas/setWidthResetAfterForcedRender.html [ Crash Failure ] crbug.com/591099 fast/css-generated-content/details-before-after-content.html [ Crash ] crbug.com/591099 fast/css-generated-content/empty-first-letter-with-columns-crash.html [ Crash ] crbug.com/714962 fast/css-generated-content/hover-inline.html [ Failure ] @@ -5928,7 +5931,7 @@ crbug.com/714962 fast/forms/calendar-picker/week-picker-mouse-operations.html [ Failure ] crbug.com/714962 fast/forms/checkbox/checkbox-focus-by-mouse.html [ Failure ] crbug.com/714962 fast/forms/color/input-color-chooser-shown-readonly.html [ Failure Pass ] -crbug.com/714962 fast/forms/color/input-color-chooser-shown.html [ Crash Failure ] +crbug.com/714962 fast/forms/color/input-color-chooser-shown.html [ Crash Failure Pass ] crbug.com/714962 fast/forms/cursor-at-editable-content-boundary.html [ Failure ] crbug.com/591099 fast/forms/datalist/input-appearance-range-with-datalist-rtl.html [ Crash ] crbug.com/591099 fast/forms/datalist/range-snap-to-datalist.html [ Crash ] @@ -6130,7 +6133,7 @@ crbug.com/714962 fast/overflow/005.html [ Failure ] crbug.com/714962 fast/overflow/006.html [ Failure ] crbug.com/714962 fast/overflow/childFocusRingClip.html [ Failure ] -crbug.com/714962 fast/overflow/clip-rects-fixed-ancestor.html [ Failure ] +crbug.com/714962 fast/overflow/clip-rects-fixed-ancestor.html [ Failure Pass ] crbug.com/714962 fast/overflow/dynamic-hidden.html [ Failure ] crbug.com/714962 fast/overflow/line-clamp-hides-trailing-anchor.html [ Failure ] crbug.com/714962 fast/overflow/overflow-float-stacking.html [ Failure ] @@ -6139,7 +6142,7 @@ crbug.com/591099 fast/overflow/overflow-visible-should-ignore-scroll.html [ Failure ] crbug.com/714962 fast/overflow/overflow-x-y.html [ Failure ] crbug.com/714962 fast/overflow/scroll-div-hide-show.html [ Failure ] -crbug.com/714962 fast/overflow/scrollRevealButton.html [ Failure ] +crbug.com/714962 fast/overflow/scrollRevealButton.html [ Failure Pass ] crbug.com/714962 fast/pagination/caret-range-outside-paged-x-rtl-vertical-rl.html [ Failure ] crbug.com/714962 fast/pagination/caret-range-outside-paged-x-vertical-rl.html [ Failure ] crbug.com/714962 fast/pagination/caret-range-outside-paged-y-rtl.html [ Failure ] @@ -6164,14 +6167,14 @@ crbug.com/591099 fast/parser/entity-comment-in-style.html [ Failure ] crbug.com/591099 fast/parser/entity-comment-in-textarea.html [ Failure ] crbug.com/591099 fast/parser/fonts.html [ Failure ] -crbug.com/591099 fast/parser/innerhtml-with-prefixed-elements.xhtml [ Failure ] +crbug.com/591099 fast/parser/innerhtml-with-prefixed-elements.xhtml [ Failure Pass ] crbug.com/591099 fast/parser/nofoo-tags-inside-paragraph.html [ Failure ] crbug.com/591099 fast/parser/noscript-with-javascript-disabled.html [ Crash Failure ] crbug.com/591099 fast/parser/open-comment-in-style.html [ Failure ] crbug.com/591099 fast/parser/open-comment-in-textarea.html [ Failure ] crbug.com/591099 fast/parser/stray-end-tags-with-attributes-002-alt-quirks.html [ Failure ] crbug.com/591099 fast/parser/stray-end-tags-with-attributes-002-alt.html [ Failure ] -crbug.com/591099 fast/parser/style-script-head-test.html [ Failure ] +crbug.com/591099 fast/parser/style-script-head-test.html [ Failure Pass ] crbug.com/591099 fast/parser/tabindex-parsing.html [ Crash ] crbug.com/591099 fast/parser/tabs-in-scripts.html [ Failure ] crbug.com/591099 fast/parser/title-error-test.html [ Failure ] @@ -6181,7 +6184,7 @@ crbug.com/591099 fast/reflections/opacity-reflection-transform.html [ Failure ] crbug.com/591099 fast/reflections/reflection-direction.html [ Failure ] crbug.com/591099 fast/reflections/reflection-masks-opacity.html [ Failure ] -crbug.com/591099 fast/reflections/reflection-masks-outset.html [ Failure ] +crbug.com/591099 fast/reflections/reflection-masks-outset.html [ Failure Pass ] crbug.com/591099 fast/reflections/reflection-masks.html [ Failure ] crbug.com/591099 fast/reflections/reflection-nesting.html [ Failure ] crbug.com/591099 fast/reflections/reflection-overflow-hidden.html [ Failure ] @@ -6360,9 +6363,6 @@ crbug.com/591099 fast/selectors/placeholder-shown-sibling-style-update.html [ Failure ] crbug.com/591099 fast/selectors/placeholder-shown-style-update.html [ Failure ] crbug.com/591099 fast/selectors/querySelector-in-range-crash.html [ Crash ] -crbug.com/714962 fast/selectors/selection-window-inactive.html [ Failure Pass ] -crbug.com/591099 fast/selectors/shadow-host-div-with-span.html [ Failure Pass ] -crbug.com/591099 fast/selectors/shadow-host-div-with-text.html [ Failure Pass ] crbug.com/591099 fast/selectors/unqualified-hover-quirks.html [ Failure ] crbug.com/591099 fast/selectors/unqualified-hover-strict.html [ Failure ] crbug.com/591099 fast/selectors/visited-descendant.html [ Failure ] @@ -6470,7 +6470,7 @@ crbug.com/591099 fast/sub-pixel/computedstylemargin.html [ Failure ] crbug.com/591099 fast/sub-pixel/float-wrap-zoom.html [ Failure ] crbug.com/591099 fast/sub-pixel/inline-block-with-padding.html [ Failure ] -crbug.com/591099 fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer.html [ Failure ] +crbug.com/591099 fast/sub-pixel/repaint-subpixel-layer-in-subpixel-composited-layer.html [ Failure Pass ] crbug.com/591099 fast/sub-pixel/selection/selection-rect-in-sub-pixel-table.html [ Crash ] crbug.com/591099 fast/sub-pixel/should-not-repaint-subpixel-composited-layer.html [ Failure ] crbug.com/714962 fast/sub-pixel/size-of-span-with-different-positions.html [ Failure ] @@ -6805,7 +6805,6 @@ crbug.com/591099 fast/text/place-rtl-ellipsis-in-inline-blocks.html [ Failure ] crbug.com/714962 fast/text/recalc-position-of-linebox-after-deleting-ellipsis.html [ Failure ] crbug.com/714962 fast/text/remove-zero-length-run.html [ Failure ] -crbug.com/714962 fast/text/selection/atsui-partial-selection.html [ Failure Pass ] crbug.com/714962 fast/text/selection/atsui-rtl-override-selection.html [ Failure ] crbug.com/714962 fast/text/selection/complex-text-rtl-selection-repaint.html [ Crash Failure Pass ] crbug.com/591099 fast/text/selection/complex-text-spaces-selection.html [ Crash Pass ] @@ -6813,7 +6812,6 @@ crbug.com/591099 fast/text/selection/flexbox-selection.html [ Failure ] crbug.com/591099 fast/text/selection/hebrew-selection.html [ Crash Failure ] crbug.com/714962 fast/text/selection/insert-text-crash.html [ Failure ] -crbug.com/714962 fast/text/selection/justified-selection.html [ Failure Pass ] crbug.com/591099 fast/text/selection/khmer-selection.html [ Failure ] crbug.com/591099 fast/text/selection/offsetForPosition-complex-fallback.html [ Failure ] crbug.com/714962 fast/text/selection/pre-wrap-overflow-selection.html [ Failure ] @@ -6821,10 +6819,6 @@ crbug.com/714962 fast/text/selection/reset-drag-on-mouse-down.html [ Failure ] crbug.com/591099 fast/text/selection/selection-hard-linebreak.html [ Failure ] crbug.com/714962 fast/text/selection/selection-multiple-runs.html [ Crash Failure Pass ] -crbug.com/714962 fast/text/selection/selection-painted-separately.html [ Failure Pass ] -crbug.com/591099 fast/text/selection/selection-painting-hidpi.html [ Failure Pass ] -crbug.com/591099 fast/text/selection/selection-rect-line-height-too-big.html [ Failure Pass ] -crbug.com/591099 fast/text/selection/selection-rect-line-height-too-small.html [ Failure Pass ] crbug.com/591099 fast/text/selection/selection-rect-rounding.html [ Failure ] crbug.com/591099 fast/text/selection/selection-with-inline-padding.html [ Crash Failure ] crbug.com/714962 fast/text/selection/shaping-selection-rect.html [ Crash Failure ] @@ -6869,7 +6863,7 @@ crbug.com/591099 fast/tokenizer/missing-style-end-tag-1.html [ Failure ] crbug.com/591099 fast/tokenizer/missing-style-end-tag-2.html [ Failure ] crbug.com/591099 fast/tokenizer/nested-cached-scripts-and-stylesheet.html [ Failure ] -crbug.com/591099 fast/tokenizer/script-after-frameset.html [ Failure ] +crbug.com/591099 fast/tokenizer/script-after-frameset.html [ Failure Pass ] crbug.com/591099 fast/tokenizer/script_extra_close.html [ Failure ] crbug.com/591099 fast/workers/shared-worker-location.html [ Failure ] crbug.com/591099 fast/workers/worker-location.html [ Failure ] @@ -7176,7 +7170,7 @@ crbug.com/714962 http/tests/css/css-resources-referrer-srcdoc.html [ Failure Pass ] crbug.com/591099 http/tests/css/css-resources-referrer.html [ Failure Pass ] crbug.com/591099 http/tests/css/shape-image-file.html [ Failure ] -crbug.com/591099 http/tests/csspaint/border-color.html [ Failure ] +crbug.com/591099 http/tests/csspaint/border-color.html [ Failure Pass ] crbug.com/591099 http/tests/csspaint/invalidation-background-image.html [ Timeout ] crbug.com/591099 http/tests/csspaint/invalidation-border-image.html [ Timeout ] crbug.com/591099 http/tests/csspaint/invalidation-content-image.html [ Timeout ] @@ -7210,7 +7204,7 @@ crbug.com/714962 http/tests/devtools/elements/edit/set-attribute.js [ Crash ] crbug.com/714962 http/tests/devtools/elements/edit/set-outer-html-2.js [ Crash ] crbug.com/714962 http/tests/devtools/elements/edit/set-outer-html-for-xhtml.js [ Crash ] -crbug.com/714962 http/tests/devtools/elements/edit/set-outer-html.js [ Crash ] +crbug.com/714962 http/tests/devtools/elements/edit/set-outer-html.js [ Crash Pass ] crbug.com/714962 http/tests/devtools/elements/edit/undo-dom-edits-2.js [ Crash ] crbug.com/714962 http/tests/devtools/elements/edit/undo-dom-edits.js [ Crash ] crbug.com/714962 http/tests/devtools/elements/edit/undo-set-outer-html-2.js [ Crash ] @@ -7219,7 +7213,7 @@ crbug.com/591099 http/tests/devtools/elements/elements-inspect-iframe-from-different-domain.js [ Crash Pass Timeout ] crbug.com/714962 http/tests/devtools/elements/elements-linkify-attributes.js [ Crash Pass ] crbug.com/714962 http/tests/devtools/elements/elements-panel-limited-children.js [ Crash ] -crbug.com/591099 http/tests/devtools/elements/elements-panel-restore-selection-when-node-comes-later.js [ Failure ] +crbug.com/591099 http/tests/devtools/elements/elements-panel-restore-selection-when-node-comes-later.js [ Failure Pass ] crbug.com/591099 http/tests/devtools/elements/elements-panel-rewrite-href.js [ Crash Failure Pass ] crbug.com/591099 http/tests/devtools/elements/elements-panel-search.js [ Crash Pass ] crbug.com/714962 http/tests/devtools/elements/elements-panel-selection-after-delete.js [ Crash ] @@ -7234,10 +7228,10 @@ crbug.com/591099 http/tests/devtools/elements/highlight/highlight-css-shapes-outside-scroll.js [ Failure ] crbug.com/591099 http/tests/devtools/elements/highlight/highlight-css-shapes-outside.js [ Failure ] crbug.com/714962 http/tests/devtools/elements/highlight/highlight-dom-updates.js [ Crash ] -crbug.com/591099 http/tests/devtools/elements/highlight/highlight-node-scaled-and-scrolled.js [ Failure ] -crbug.com/591099 http/tests/devtools/elements/highlight/highlight-node-scaled.js [ Failure ] -crbug.com/591099 http/tests/devtools/elements/highlight/highlight-node-scroll.js [ Failure ] -crbug.com/591099 http/tests/devtools/elements/highlight/highlight-node.js [ Failure ] +crbug.com/591099 http/tests/devtools/elements/highlight/highlight-node-scaled-and-scrolled.js [ Failure Pass ] +crbug.com/591099 http/tests/devtools/elements/highlight/highlight-node-scaled.js [ Failure Pass ] +crbug.com/591099 http/tests/devtools/elements/highlight/highlight-node-scroll.js [ Failure Pass ] +crbug.com/591099 http/tests/devtools/elements/highlight/highlight-node.js [ Failure Pass ] crbug.com/714962 http/tests/devtools/elements/iframe-load-event.js [ Crash Pass ] crbug.com/714962 http/tests/devtools/elements/insert-node.js [ Crash ] crbug.com/714962 http/tests/devtools/elements/inspect-pseudo-element.js [ Timeout ] @@ -7278,7 +7272,7 @@ crbug.com/714962 http/tests/devtools/layers/layer-canvas-log.js [ Failure ] crbug.com/591099 http/tests/devtools/network/network-columns-visible.js [ Failure Timeout ] crbug.com/591099 http/tests/devtools/network/network-datareceived.js [ Failure ] -crbug.com/591099 http/tests/devtools/persistence/automapping-sourcemap-nameclash.js [ Failure ] +crbug.com/591099 http/tests/devtools/persistence/automapping-sourcemap-nameclash.js [ Failure Pass ] crbug.com/591099 http/tests/devtools/persistence/persistence-tabbed-editor-opens-filesystem-uisourcecode.js [ Failure Timeout ] crbug.com/591099 http/tests/devtools/runtime/runtime-getProperties.js [ Failure ] crbug.com/714962 http/tests/devtools/service-workers/service-workers-view.js [ Failure ] @@ -7286,14 +7280,13 @@ crbug.com/591099 http/tests/devtools/sources/debugger-ui/function-generator-details.js [ Failure ] crbug.com/591099 http/tests/devtools/sources/debugger/live-edit-no-reveal.js [ Failure Pass ] crbug.com/591099 http/tests/devtools/sources/debugger/properties-special.js [ Failure ] -crbug.com/591099 http/tests/devtools/startup/reattach-after-editing-styles.html [ Crash Pass Timeout ] crbug.com/591099 http/tests/devtools/text-autosizing-override.js [ Failure ] crbug.com/714962 http/tests/devtools/tracing/scroll-invalidations.js [ Failure ] crbug.com/591099 http/tests/devtools/tracing/timeline-misc/timeline-bound-function.js [ Crash Failure ] crbug.com/714962 http/tests/devtools/tracing/timeline-misc/timeline-grouped-invalidations.js [ Failure ] crbug.com/591099 http/tests/devtools/tracing/timeline-paint/paint-profiler-update.js [ Crash Timeout ] crbug.com/714962 http/tests/devtools/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations.js [ Failure ] -crbug.com/714962 http/tests/devtools/tracing/timeline-paint/timeline-paint.js [ Failure ] +crbug.com/714962 http/tests/devtools/tracing/timeline-paint/timeline-paint.js [ Failure Pass ] crbug.com/591099 http/tests/devtools/websocket/network-preserve-selection-on-frame-receive.js [ Crash Pass ] crbug.com/591099 http/tests/feature-policy-experimental-features/vibrate-allowed-by-container-policy-relocate-and-no-reload.html [ Timeout ] crbug.com/591099 http/tests/feature-policy-experimental-features/vibrate-allowed-by-container-policy-relocate-and-reload.html [ Timeout ] @@ -7394,7 +7387,7 @@ crbug.com/591099 http/tests/navigation/timerredirect-goback.html [ Failure ] crbug.com/591099 http/tests/origin_trials/sample-api-workers.html [ Pass ] crbug.com/591099 http/tests/permissions/test-api-surface.html [ Pass ] -crbug.com/591099 http/tests/previews/client-lofi-sprite.html [ Failure ] +crbug.com/591099 http/tests/previews/client-lofi-sprite.html [ Failure Pass ] crbug.com/591099 http/tests/security/XFrameOptions/x-frame-options-cached.html [ Failure ] crbug.com/714962 http/tests/security/anchor-download-allow-blob.html [ Failure ] crbug.com/714962 http/tests/security/anchor-download-allow-data.html [ Failure ] @@ -7526,7 +7519,7 @@ crbug.com/591099 ietestcenter/css3/bordersbackgrounds/order-of-images.htm [ Failure ] crbug.com/714962 ietestcenter/css3/flexbox/flexbox-layout-003.htm [ Failure Pass ] crbug.com/591099 ietestcenter/css3/multicolumn/column-block-formatting-context-001.htm [ Failure ] -crbug.com/591099 ietestcenter/css3/multicolumn/column-containing-block-001.htm [ Failure ] +crbug.com/591099 ietestcenter/css3/multicolumn/column-containing-block-001.htm [ Failure Pass ] crbug.com/591099 ietestcenter/css3/multicolumn/column-containing-block-003.htm [ Failure ] crbug.com/714962 ietestcenter/css3/multicolumn/column-width-applies-to-001.htm [ Failure ] crbug.com/714962 ietestcenter/css3/multicolumn/column-width-applies-to-002.htm [ Failure ] @@ -7579,13 +7572,13 @@ crbug.com/714962 images/drag-image-transformed-parent.html [ Failure ] crbug.com/591099 images/embed-does-not-propagate-dimensions-to-object-ancestor.html [ Failure ] crbug.com/591099 images/exif-orientation-css.html [ Failure ] -crbug.com/591099 images/exif-orientation-height-image-document.html [ Failure ] +crbug.com/591099 images/exif-orientation-height-image-document.html [ Failure Pass ] crbug.com/591099 images/exif-orientation-image-document.html [ Failure ] crbug.com/591099 images/exif-orientation.html [ Failure ] crbug.com/591099 images/favicon-as-image.html [ Failure ] crbug.com/591099 images/gif-loop-count.html [ Failure ] crbug.com/591099 images/gif-short-app-extension-string.html [ Failure ] -crbug.com/591099 images/gray-scale-jpeg-with-color-profile.html [ Failure ] +crbug.com/591099 images/gray-scale-jpeg-with-color-profile.html [ Failure Pass ] crbug.com/591099 images/gray-scale-png-with-color-profile.html [ Failure ] crbug.com/591099 images/icon-0colors.html [ Failure ] crbug.com/591099 images/icon-decoding.html [ Failure ] @@ -7676,11 +7669,11 @@ crbug.com/591099 media/controls/video-overlay-cast-light-rendering.html [ Failure ] crbug.com/714962 media/controls/volumechange-stopimmediatepropagation.html [ Failure Pass ] crbug.com/591099 media/media-document-audio-repaint.html [ Failure ] -crbug.com/591099 media/track/track-cue-rendering-horizontal.html [ Failure ] +crbug.com/591099 media/track/track-cue-rendering-horizontal.html [ Failure Pass ] crbug.com/714962 media/track/track-cue-rendering-position-auto-rtl.html [ Failure ] crbug.com/714962 media/track/track-cue-rendering-position-auto.html [ Failure ] crbug.com/714962 media/track/track-cue-rendering-transformed-video.html [ Failure ] -crbug.com/591099 media/track/track-cue-rendering-vertical.html [ Failure ] +crbug.com/591099 media/track/track-cue-rendering-vertical.html [ Failure Pass ] crbug.com/591099 media/track/track-webvtt-non-snap-to-lines.html [ Failure ] crbug.com/591099 media/video-aspect-ratio.html [ Failure ] crbug.com/591099 media/video-canvas-alpha.html [ Failure ] @@ -7704,13 +7697,13 @@ crbug.com/591099 overflow/overflow-basic-002.html [ Pass ] crbug.com/591099 overflow/overflow-position-003.html [ Failure ] crbug.com/591099 overflow/overflow-transform-perspective.html [ Failure ] -crbug.com/591099 paint/background/fieldset-legend-background-shadow-border-radius.html [ Failure ] -crbug.com/591099 paint/background/rounded-clip-fractional-offset.html [ Failure ] +crbug.com/591099 paint/background/fieldset-legend-background-shadow-border-radius.html [ Failure Pass ] +crbug.com/591099 paint/background/rounded-clip-fractional-offset.html [ Failure Pass ] crbug.com/714962 paint/clipath/clip-path-bigger-than-border-box-visual-rect.html [ Failure ] crbug.com/714962 paint/clipath/clip-path-bigger-than-visual-overflow.html [ Failure ] crbug.com/591099 paint/clipath/clip-path-with-background-and-box-behind.html [ Failure ] crbug.com/591099 paint/filters/clip-filter-overflow-clip.html [ Failure ] -crbug.com/591099 paint/filters/clip-under-filter.html [ Failure ] +crbug.com/591099 paint/filters/clip-under-filter.html [ Failure Pass ] crbug.com/714962 paint/float/float-text-clip.html [ Crash ] crbug.com/591099 paint/frames/frameset-with-stacking-context-and-not-stacking-context-children.html [ Failure ] crbug.com/591099 paint/frames/frameset-with-stacking-contexts.html [ Failure ] @@ -7718,25 +7711,25 @@ crbug.com/714962 paint/inline/floating-inline.html [ Crash ] crbug.com/591099 paint/inline/focus-ring-under-absolute-with-relative-continuation.html [ Failure ] crbug.com/591099 paint/inline/outline-offset.html [ Failure ] -crbug.com/591099 paint/input/textarea-crash.html [ Crash ] +crbug.com/591099 paint/input/textarea-crash.html [ Crash Pass ] crbug.com/591099 paint/invalidation/4774354.html [ Failure ] crbug.com/591099 paint/invalidation/4776765.html [ Failure ] -crbug.com/591099 paint/invalidation/background/animated-gif-background.html [ Failure ] -crbug.com/591099 paint/invalidation/background/animated-png-background.html [ Failure ] -crbug.com/591099 paint/invalidation/background/animated-webp-background.html [ Failure ] +crbug.com/591099 paint/invalidation/background/animated-gif-background.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/background/animated-png-background.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/background/animated-webp-background.html [ Failure Pass ] crbug.com/591099 paint/invalidation/background/background-currentColor-repaint.html [ Failure ] -crbug.com/591099 paint/invalidation/background/background-generated.html [ Failure ] +crbug.com/591099 paint/invalidation/background/background-generated.html [ Failure Pass ] crbug.com/591099 paint/invalidation/background/background-image-paint-invalidation-large-abspos-div.html [ Failure ] -crbug.com/591099 paint/invalidation/background/background-image-paint-invalidation-small-document.html [ Failure ] +crbug.com/591099 paint/invalidation/background/background-image-paint-invalidation-small-document.html [ Failure Pass ] crbug.com/591099 paint/invalidation/background/background-image-paint-invalidation.html [ Failure ] crbug.com/591099 paint/invalidation/background/background-misaligned.html [ Failure ] -crbug.com/591099 paint/invalidation/background/background-resize-height.html [ Failure ] -crbug.com/591099 paint/invalidation/background/background-shorthand-with-gradient-and-height-changes.html [ Failure ] -crbug.com/591099 paint/invalidation/background/background-size-auto-with-gradient-and-height-changes.html [ Failure ] +crbug.com/591099 paint/invalidation/background/background-resize-height.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/background/background-shorthand-with-gradient-and-height-changes.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/background/background-size-auto-with-gradient-and-height-changes.html [ Failure Pass ] crbug.com/591099 paint/invalidation/background/backgroundSizeRepaint.html [ Failure ] -crbug.com/591099 paint/invalidation/background/body-background-image.html [ Failure ] +crbug.com/591099 paint/invalidation/background/body-background-image.html [ Failure Pass ] crbug.com/714962 paint/invalidation/background/change-text-content-and-background-color.html [ Failure ] -crbug.com/591099 paint/invalidation/background/multiple-backgrounds-style-change.html [ Failure ] +crbug.com/591099 paint/invalidation/background/multiple-backgrounds-style-change.html [ Failure Pass ] crbug.com/591099 paint/invalidation/background/view-background-from-body-2.html [ Failure ] crbug.com/591099 paint/invalidation/background/viewport-gradient-background-html-move-overflow.html [ Failure ] crbug.com/591099 paint/invalidation/background/viewport-gradient-background-html-resize-overflow.html [ Failure ] @@ -7744,33 +7737,33 @@ crbug.com/591099 paint/invalidation/block-layout-inline-children-replaced.html [ Failure ] crbug.com/591099 paint/invalidation/block-no-inflow-children.html [ Failure ] crbug.com/591099 paint/invalidation/block-shift-repaint.html [ Failure ] -crbug.com/591099 paint/invalidation/box/border-current-color.html [ Failure ] -crbug.com/591099 paint/invalidation/box/border-image-outset-add-repaint.html [ Failure ] -crbug.com/591099 paint/invalidation/box/border-image-outset-change-repaint.html [ Failure ] +crbug.com/591099 paint/invalidation/box/border-current-color.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/box/border-image-outset-add-repaint.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/box/border-image-outset-change-repaint.html [ Failure Pass ] crbug.com/591099 paint/invalidation/box/border-radius-repaint-2.html [ Failure ] crbug.com/591099 paint/invalidation/box/border-radius-repaint.html [ Failure ] -crbug.com/591099 paint/invalidation/box/border-radius-without-border.html [ Failure ] +crbug.com/591099 paint/invalidation/box/border-radius-without-border.html [ Failure Pass ] crbug.com/591099 paint/invalidation/box/border-repaint-glitch.html [ Failure ] crbug.com/591099 paint/invalidation/box/box-inline-resize.html [ Crash Failure ] -crbug.com/591099 paint/invalidation/box/box-shadow-add-repaint.html [ Failure ] -crbug.com/591099 paint/invalidation/box/box-shadow-change-repaint.html [ Failure ] +crbug.com/591099 paint/invalidation/box/box-shadow-add-repaint.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/box/box-shadow-change-repaint.html [ Failure Pass ] crbug.com/591099 paint/invalidation/box/box-shadow-dynamic.html [ Failure ] -crbug.com/591099 paint/invalidation/box/box-shadow-inset-repaint.html [ Failure ] -crbug.com/591099 paint/invalidation/box/box-sizing-border-keeping-size.html [ Failure ] -crbug.com/591099 paint/invalidation/box/box-sizing-padding-keeping-size.html [ Failure ] +crbug.com/591099 paint/invalidation/box/box-shadow-inset-repaint.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/box/box-sizing-border-keeping-size.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/box/box-sizing-padding-keeping-size.html [ Failure Pass ] crbug.com/591099 paint/invalidation/box/box-sizing.html [ Failure ] -crbug.com/591099 paint/invalidation/box/hover-pseudo-borders-whitespace.html [ Failure ] +crbug.com/591099 paint/invalidation/box/hover-pseudo-borders-whitespace.html [ Failure Pass ] crbug.com/591099 paint/invalidation/box/hover-pseudo-borders.html [ Failure ] crbug.com/591099 paint/invalidation/box/invalidate-box-shadow-currentColor.html [ Failure ] -crbug.com/591099 paint/invalidation/box/margin.html [ Failure ] -crbug.com/591099 paint/invalidation/box/negative-shadow-box-expand.html [ Failure ] +crbug.com/591099 paint/invalidation/box/margin.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/box/negative-shadow-box-expand.html [ Failure Pass ] crbug.com/591099 paint/invalidation/box/negative-shadow-box-shrink.html [ Failure ] -crbug.com/591099 paint/invalidation/box/padding-border-keeping-border-box-and-content-box.html [ Failure ] +crbug.com/591099 paint/invalidation/box/padding-border-keeping-border-box-and-content-box.html [ Failure Pass ] crbug.com/591099 paint/invalidation/box/padding-keeping-content-size.html [ Failure ] crbug.com/591099 paint/invalidation/box/padding-keeping-visual-size.html [ Failure ] crbug.com/591099 paint/invalidation/box/resize-with-border.html [ Failure ] -crbug.com/591099 paint/invalidation/box/shadow-box-resize-writing-mode.html [ Failure ] -crbug.com/591099 paint/invalidation/box/shadow-box-resize.html [ Failure ] +crbug.com/591099 paint/invalidation/box/shadow-box-resize-writing-mode.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/box/shadow-box-resize.html [ Failure Pass ] crbug.com/591099 paint/invalidation/bugzilla-3509.html [ Failure ] crbug.com/591099 paint/invalidation/bugzilla-5699.html [ Failure ] crbug.com/591099 paint/invalidation/bugzilla-6278.html [ Failure ] @@ -7781,8 +7774,8 @@ crbug.com/714962 paint/invalidation/caret-outside-block.html [ Failure ] crbug.com/714962 paint/invalidation/caret-subpixel.html [ Failure ] crbug.com/591099 paint/invalidation/clip/caret-ancestor-clip-change.html [ Failure ] -crbug.com/591099 paint/invalidation/clip/clip-path-constant-repaint.html [ Failure ] -crbug.com/591099 paint/invalidation/clip/clip-path-resize.html [ Failure ] +crbug.com/591099 paint/invalidation/clip/clip-path-constant-repaint.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/clip/clip-path-resize.html [ Failure Pass ] crbug.com/591099 paint/invalidation/clip/clip-unclip-and-change.html [ Failure ] crbug.com/591099 paint/invalidation/clip/clip-with-layout-delta.html [ Failure ] crbug.com/591099 paint/invalidation/clip/clip-with-transform-resize.html [ Failure ] @@ -7795,7 +7788,7 @@ crbug.com/714962 paint/invalidation/clip/repaint-subsequence-on-ancestor-clip-change-complex.html [ Failure ] crbug.com/591099 paint/invalidation/clip/repaint-tile-clipped.html [ Crash ] crbug.com/591099 paint/invalidation/clip/replaced-clipped-positioned-not-wrong-incremental-repainting.html [ Failure ] -crbug.com/591099 paint/invalidation/clip/resize-with-border-clipped.html [ Failure ] +crbug.com/591099 paint/invalidation/clip/resize-with-border-clipped.html [ Failure Pass ] crbug.com/591099 paint/invalidation/clip/subtree-root-clip-2.html [ Failure ] crbug.com/591099 paint/invalidation/clip/subtree-root-clip-3.html [ Failure ] crbug.com/591099 paint/invalidation/clip/subtree-root-clip.html [ Failure ] @@ -7804,11 +7797,11 @@ crbug.com/591099 paint/invalidation/compositing/become-overlay-composited-layer.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/child-of-sub-pixel-offset-composited-layer.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/chunk-reorder.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/clipping-should-not-repaint-composited-descendants.html [ Failure ] +crbug.com/591099 paint/invalidation/compositing/clipping-should-not-repaint-composited-descendants.html [ Failure Pass ] crbug.com/591099 paint/invalidation/compositing/column-span-under-composited-column-child.html [ Crash ] crbug.com/591099 paint/invalidation/compositing/composited-document-element.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/composited-float-under-composited-inline-individual.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/composited-float-under-composited-inline.html [ Failure ] +crbug.com/591099 paint/invalidation/compositing/composited-float-under-composited-inline-individual.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/compositing/composited-float-under-composited-inline.html [ Failure Pass ] crbug.com/714962 paint/invalidation/compositing/composited-inline-change-text-data-keep-geometry.html [ Crash ] crbug.com/714962 paint/invalidation/compositing/composited-non-stacking-context-not-invalidation-container.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/compositing-reason-removed.html [ Failure ] @@ -7816,19 +7809,19 @@ crbug.com/591099 paint/invalidation/compositing/containing-block-added.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/containing-block-removed-individual.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/containing-block-removed.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/content-into-overflow.html [ Failure ] +crbug.com/591099 paint/invalidation/compositing/content-into-overflow.html [ Failure Pass ] crbug.com/591099 paint/invalidation/compositing/dont-invalidate-root-layer-when-composited-layer-becomes-visible.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/fixed-scroll-in-empty-root-layer.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/float-under-composited-inline.html [ Failure ] +crbug.com/591099 paint/invalidation/compositing/float-under-composited-inline.html [ Failure Pass ] crbug.com/591099 paint/invalidation/compositing/iframe-clip-removed.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/iframe-inside-squashed-layer.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/invalidate-paint-in-iframe-in-composited-layer.html [ Failure ] +crbug.com/591099 paint/invalidation/compositing/invalidate-paint-in-iframe-in-composited-layer.html [ Failure Pass ] crbug.com/591099 paint/invalidation/compositing/invalidate-when-leaving-squashed-layer.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/invalidation-for-subpixel-offset-of-squashed-layer.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/invalidations-on-composited-layers.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/invalidations-with-large-negative-margin.html [ Failure ] +crbug.com/591099 paint/invalidation/compositing/invalidation-for-subpixel-offset-of-squashed-layer.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/compositing/invalidations-on-composited-layers.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/compositing/invalidations-with-large-negative-margin.html [ Failure Pass ] crbug.com/591099 paint/invalidation/compositing/layer-repaint-rects.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/layer-repaint.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/multi-subsequence-composited.html [ Failure ] @@ -7836,41 +7829,41 @@ crbug.com/591099 paint/invalidation/compositing/newly-composited-on-scroll.html [ Crash Pass ] crbug.com/591099 paint/invalidation/compositing/opacity-between-absolute.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/opacity-between-absolute2.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/overflow-into-content.html [ Failure ] +crbug.com/591099 paint/invalidation/compositing/overflow-into-content.html [ Failure Pass ] crbug.com/591099 paint/invalidation/compositing/overlap-test-with-filter.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/page-scale-repaint.html [ Failure ] +crbug.com/591099 paint/invalidation/compositing/page-scale-repaint.html [ Failure Pass ] crbug.com/591099 paint/invalidation/compositing/pointer-events-composited-scrolling.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/remove-squashed-layer-plus-move.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/repaint-squashed-layer-in-rect.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/repaint-via-layout-offset.html [ Failure ] +crbug.com/591099 paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/compositing/repaint-squashed-layer-in-rect.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/compositing/repaint-via-layout-offset.html [ Failure Pass ] crbug.com/591099 paint/invalidation/compositing/resize-repaint.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/resize-squashing-layer-that-needs-full-repaint.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/scroll-fixed-layer-no-content.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/scroll-fixed-layer-out-of-view.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/scroll-fixed-squahed-layer.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/scrolling-without-painting.html [ Failure ] +crbug.com/591099 paint/invalidation/compositing/scroll-fixed-layer-no-content.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/compositing/scroll-fixed-layer-out-of-view.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/compositing/scroll-fixed-squahed-layer.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/compositing/scrolling-without-painting.html [ Failure Pass ] crbug.com/591099 paint/invalidation/compositing/should-invoke-deferred-compositing.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/should-not-clip-composited-viewport-scrolling-layer.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/should-not-repaint-composited-descendants-on-overflow-change.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/should-not-repaint-composited-descendants.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/should-not-repaint-composited-filter.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/should-not-repaint-composited-opacity.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/should-not-repaint-composited-transform.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/should-not-repaint-composited-z-index.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/should-not-repaint-move-backface-hidden.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/should-not-repaint-scrolling-contents-outline-change.html [ Failure ] +crbug.com/591099 paint/invalidation/compositing/should-not-repaint-composited-filter.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/compositing/should-not-repaint-composited-opacity.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/compositing/should-not-repaint-composited-transform.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/compositing/should-not-repaint-composited-z-index.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/compositing/should-not-repaint-move-backface-hidden.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/compositing/should-not-repaint-scrolling-contents-outline-change.html [ Failure Pass ] crbug.com/591099 paint/invalidation/compositing/squash-partial-repaint-inside-squashed-layer.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/squashing-inside-preserve-3d-element.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/stacked-float-under-composited-inline.html [ Failure ] +crbug.com/591099 paint/invalidation/compositing/squashing-inside-preserve-3d-element.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/compositing/stacked-float-under-composited-inline.html [ Failure Pass ] crbug.com/591099 paint/invalidation/compositing/subpixel-offset-scaled-transform-composited.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/text-color-change.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/text-match-highlight.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/tricky-element-removal-crash.html [ Failure ] crbug.com/591099 paint/invalidation/compositing/updating-scrolling-container-and-content.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/updating-scrolling-container.html [ Failure ] -crbug.com/591099 paint/invalidation/compositing/updating-scrolling-content.html [ Failure ] +crbug.com/591099 paint/invalidation/compositing/updating-scrolling-container.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/compositing/updating-scrolling-content.html [ Failure Pass ] crbug.com/591099 paint/invalidation/crbug-371640-2.html [ Failure ] crbug.com/591099 paint/invalidation/crbug-371640-3.html [ Failure ] crbug.com/591099 paint/invalidation/crbug-371640-4.html [ Failure ] @@ -7884,22 +7877,22 @@ crbug.com/591099 paint/invalidation/delete-into-nested-block.html [ Failure ] crbug.com/591099 paint/invalidation/details-open-repaint.html [ Crash ] crbug.com/714962 paint/invalidation/empty-object-move-and-resize.html [ Failure ] -crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-composite-1.html [ Failure ] -crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-composite-2.html [ Failure ] +crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-composite-1.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-composite-2.html [ Failure Pass ] crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-composite-3.html [ Failure ] -crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-composite-4.html [ Failure ] -crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-composite-5.html [ Failure ] -crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-composite-6.html [ Failure ] -crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-displacement.html [ Failure ] +crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-composite-4.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-composite-5.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-composite-6.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-displacement.html [ Failure Pass ] crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-gaussianblur-xonly.html [ Failure ] crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-gaussianblur-yonly.html [ Failure ] crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-gaussianblur.html [ Failure ] crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-lighting.html [ Failure ] -crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-merge.html [ Failure ] -crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-morphology-xonly.html [ Failure ] -crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-morphology-yonly.html [ Failure ] -crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-morphology.html [ Failure ] -crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-offset.html [ Failure ] +crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-merge.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-morphology-xonly.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-morphology-yonly.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-morphology.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-offset.html [ Failure Pass ] crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-primitive-attr-mutation.html [ Failure ] crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-primitive-attr-removal.html [ Failure ] crbug.com/591099 paint/invalidation/filters/effect-reference-repaint-primitive-removed.html [ Failure ] @@ -7937,7 +7930,7 @@ crbug.com/591099 paint/invalidation/float-in-new-block-with-layout-delta.html [ Failure ] crbug.com/591099 paint/invalidation/float-move-during-layout.html [ Failure ] crbug.com/591099 paint/invalidation/float-new-in-block.html [ Failure ] -crbug.com/591099 paint/invalidation/forms/button-checkbox-click-method-repaint.html [ Failure ] +crbug.com/591099 paint/invalidation/forms/button-checkbox-click-method-repaint.html [ Failure Pass ] crbug.com/591099 paint/invalidation/forms/button-reset-focus-by-mouse-then-keydown.html [ Failure ] crbug.com/591099 paint/invalidation/forms/checkbox-focus-by-mouse-then-keydown.html [ Failure ] crbug.com/591099 paint/invalidation/forms/radio-focus-by-mouse-then-keydown.html [ Failure ] @@ -7953,11 +7946,11 @@ crbug.com/591099 paint/invalidation/gradients-em-stops-repaint.html [ Failure ] crbug.com/591099 paint/invalidation/iframe-display-block-to-display-none.html [ Failure ] crbug.com/591099 paint/invalidation/iframe-display-none-to-display-block.html [ Failure ] -crbug.com/591099 paint/invalidation/iframe-rounding.html [ Failure ] -crbug.com/591099 paint/invalidation/image/animated-gif-transformed-offscreen.html [ Failure ] +crbug.com/591099 paint/invalidation/iframe-rounding.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/image/animated-gif-transformed-offscreen.html [ Failure Pass ] crbug.com/714962 paint/invalidation/image/canvas-composite-repaint-by-all-imagesource.html [ Failure ] crbug.com/714962 paint/invalidation/image/percent-size-image-resize-container.html [ Failure ] -crbug.com/591099 paint/invalidation/in-scaled-iframe.html [ Failure ] +crbug.com/591099 paint/invalidation/in-scaled-iframe.html [ Failure Pass ] crbug.com/591099 paint/invalidation/inline-block-resize.html [ Failure ] crbug.com/591099 paint/invalidation/inline-color-change.html [ Failure ] crbug.com/591099 paint/invalidation/inline-reflow.html [ Failure ] @@ -7969,9 +7962,9 @@ crbug.com/591099 paint/invalidation/invalidation-on-foreground-graphics-layer.html [ Failure ] crbug.com/591099 paint/invalidation/invalidation-with-zero-size-object.html [ Failure ] crbug.com/591099 paint/invalidation/invisible-objects.html [ Failure ] -crbug.com/591099 paint/invalidation/layer-full-repaint.html [ Failure ] +crbug.com/591099 paint/invalidation/layer-full-repaint.html [ Failure Pass ] crbug.com/591099 paint/invalidation/layer-hide-when-needs-layout.html [ Failure ] -crbug.com/591099 paint/invalidation/layer-visibility.html [ Failure ] +crbug.com/591099 paint/invalidation/layer-visibility.html [ Failure Pass ] crbug.com/591099 paint/invalidation/line-flow-with-floats-1.html [ Failure ] crbug.com/591099 paint/invalidation/line-flow-with-floats-10.html [ Failure ] crbug.com/591099 paint/invalidation/line-flow-with-floats-2.html [ Failure ] @@ -7988,7 +7981,7 @@ crbug.com/591099 paint/invalidation/make-children-non-inline.html [ Failure ] crbug.com/591099 paint/invalidation/mix-blend-mode-separate-stacking-context.html [ Failure ] crbug.com/714962 paint/invalidation/multi-layout-one-frame.html [ Failure ] -crbug.com/591099 paint/invalidation/multicol/column-float-under-stacked-inline.html [ Failure ] +crbug.com/591099 paint/invalidation/multicol/column-float-under-stacked-inline.html [ Failure Pass ] crbug.com/591099 paint/invalidation/multicol/column-rules-fixed-height.html [ Failure ] crbug.com/591099 paint/invalidation/multicol/multicol-as-paint-container.html [ Failure ] crbug.com/591099 paint/invalidation/multicol/multicol-nested.html [ Failure ] @@ -8022,19 +8015,19 @@ crbug.com/591099 paint/invalidation/outline/layer-outline-horizontal.html [ Failure ] crbug.com/591099 paint/invalidation/outline/layer-outline.html [ Failure ] crbug.com/591099 paint/invalidation/outline/outline-add-repaint.html [ Failure ] -crbug.com/591099 paint/invalidation/outline/outline-become-affected-by-descendant.html [ Failure ] -crbug.com/591099 paint/invalidation/outline/outline-become-not-affected-by-descendant.html [ Failure ] +crbug.com/591099 paint/invalidation/outline/outline-become-affected-by-descendant.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/outline/outline-become-not-affected-by-descendant.html [ Failure Pass ] crbug.com/591099 paint/invalidation/outline/outline-change-continuations.html [ Failure ] crbug.com/591099 paint/invalidation/outline/outline-change-invalidation.html [ Failure ] -crbug.com/591099 paint/invalidation/outline/outline-change-offset.html [ Failure ] +crbug.com/591099 paint/invalidation/outline/outline-change-offset.html [ Failure Pass ] crbug.com/591099 paint/invalidation/outline/outline-change-repaint.html [ Failure ] crbug.com/591099 paint/invalidation/outline/outline-change-vertical-rl.html [ Failure ] crbug.com/591099 paint/invalidation/outline/outline-child-repaint.html [ Failure ] crbug.com/591099 paint/invalidation/outline/outline-containing-image-in-non-standard-mode.html [ Failure ] crbug.com/591099 paint/invalidation/outline/outline-continuations.html [ Failure ] -crbug.com/591099 paint/invalidation/outline/outline-current-color.html [ Failure ] +crbug.com/591099 paint/invalidation/outline/outline-current-color.html [ Failure Pass ] crbug.com/591099 paint/invalidation/outline/outline-inset.html [ Failure ] -crbug.com/591099 paint/invalidation/outline/outline-not-affected-by-descendant.html [ Failure ] +crbug.com/591099 paint/invalidation/outline/outline-not-affected-by-descendant.html [ Failure Pass ] crbug.com/591099 paint/invalidation/outline/outline-repaint-glitch.html [ Failure ] crbug.com/591099 paint/invalidation/outline/outline-shrinking.html [ Failure ] crbug.com/591099 paint/invalidation/overflow/align-items-overflow-change.html [ Failure ] @@ -8043,7 +8036,7 @@ crbug.com/591099 paint/invalidation/overflow/composited-overflow-with-borderbox-background.html [ Failure ] crbug.com/591099 paint/invalidation/overflow/composited-overflow-with-local-background.html [ Failure ] crbug.com/591099 paint/invalidation/overflow/composited-overflow-with-negative-offset-outline.html [ Failure ] -crbug.com/591099 paint/invalidation/overflow/composited-vertical-rl-overflow.html [ Failure ] +crbug.com/591099 paint/invalidation/overflow/composited-vertical-rl-overflow.html [ Failure Pass ] crbug.com/591099 paint/invalidation/overflow/content-into-overflow.html [ Failure ] crbug.com/591099 paint/invalidation/overflow/erase-overflow.html [ Failure ] crbug.com/591099 paint/invalidation/overflow/fixed-position-transparency-with-overflow.html [ Failure ] @@ -8063,7 +8056,7 @@ crbug.com/591099 paint/invalidation/overflow/negative-text-indent-with-overflow-hidden.html [ Failure ] crbug.com/591099 paint/invalidation/overflow/opacity-change-on-overflow-float.html [ Failure ] crbug.com/591099 paint/invalidation/overflow/overflow-changed-on-child-of-composited-layer.html [ Failure ] -crbug.com/591099 paint/invalidation/overflow/overflow-clip-subtree-layout.html [ Failure ] +crbug.com/591099 paint/invalidation/overflow/overflow-clip-subtree-layout.html [ Failure Pass ] crbug.com/714962 paint/invalidation/overflow/overflow-delete-line.html [ Failure ] crbug.com/591099 paint/invalidation/overflow/overflow-hidden-to-visible.html [ Failure ] crbug.com/591099 paint/invalidation/overflow/overflow-hide.html [ Failure ] @@ -8071,14 +8064,14 @@ crbug.com/714962 paint/invalidation/overflow/overflow-outline-repaint.html [ Failure ] crbug.com/591099 paint/invalidation/overflow/overflow-show.html [ Failure ] crbug.com/591099 paint/invalidation/overflow/paged-with-overflowing-block-rl.html [ Failure ] -crbug.com/591099 paint/invalidation/overflow/rel-positioned-inline-with-overflow.html [ Failure ] +crbug.com/591099 paint/invalidation/overflow/rel-positioned-inline-with-overflow.html [ Failure Pass ] crbug.com/591099 paint/invalidation/overflow/repaint-resized-overflow.html [ Failure ] -crbug.com/591099 paint/invalidation/overflow/resize-child-within-overflow.html [ Failure ] +crbug.com/591099 paint/invalidation/overflow/resize-child-within-overflow.html [ Failure Pass ] crbug.com/591099 paint/invalidation/overflow/trailing-floats-root-line-box-overflow.html [ Failure ] crbug.com/591099 paint/invalidation/overflow/vertical-overflow-child.html [ Failure ] crbug.com/591099 paint/invalidation/overflow/vertical-overflow-parent.html [ Failure ] crbug.com/591099 paint/invalidation/overflow/vertical-overflow-same.html [ Failure ] -crbug.com/591099 paint/invalidation/overflow/vertical-rl-overflow.html [ Failure ] +crbug.com/591099 paint/invalidation/overflow/vertical-rl-overflow.html [ Failure Pass ] crbug.com/591099 paint/invalidation/overhanging-float-detach-repaint.html [ Failure ] crbug.com/714962 paint/invalidation/paint-caret-in-div-with-negative-indent.html [ Failure ] crbug.com/591099 paint/invalidation/paint-invalidation-with-opacity.html [ Failure ] @@ -8087,22 +8080,22 @@ crbug.com/591099 paint/invalidation/position/absolute-layer-specified-left-or-right-auto-width-moved-vertically.html [ Failure ] crbug.com/591099 paint/invalidation/position/absolute-margin-change-repaint.html [ Failure ] crbug.com/591099 paint/invalidation/position/absolute-position-change-containing-block.html [ Failure ] -crbug.com/591099 paint/invalidation/position/absolute-position-changed.html [ Failure ] +crbug.com/591099 paint/invalidation/position/absolute-position-changed.html [ Failure Pass ] crbug.com/591099 paint/invalidation/position/absolute-position-moved.html [ Failure ] crbug.com/591099 paint/invalidation/position/abspos-shift-image-incorrect-repaint.html [ Failure ] crbug.com/591099 paint/invalidation/position/align-content-position-change-grid.html [ Failure ] crbug.com/591099 paint/invalidation/position/block-layout-inline-children-float-positioned.html [ Failure ] crbug.com/591099 paint/invalidation/position/containing-block-position-change.html [ Failure ] -crbug.com/591099 paint/invalidation/position/fixed-element-repaint-after-compositing-update.html [ Failure ] -crbug.com/591099 paint/invalidation/position/fixed-margin-change-repaint.html [ Failure ] +crbug.com/591099 paint/invalidation/position/fixed-element-repaint-after-compositing-update.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/position/fixed-margin-change-repaint.html [ Failure Pass ] crbug.com/591099 paint/invalidation/position/fixed-position-layer-moved.html [ Failure ] crbug.com/591099 paint/invalidation/position/fixed-scale.html [ Failure ] crbug.com/591099 paint/invalidation/position/fixed-to-relative-position-with-absolute-child.html [ Failure ] -crbug.com/591099 paint/invalidation/position/fixed-tranformed.html [ Failure ] -crbug.com/591099 paint/invalidation/position/fixed.html [ Failure ] +crbug.com/591099 paint/invalidation/position/fixed-tranformed.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/position/fixed.html [ Failure Pass ] crbug.com/591099 paint/invalidation/position/inline-relative-positioned.html [ Failure ] crbug.com/591099 paint/invalidation/position/intermediate-layout-position.html [ Failure ] -crbug.com/591099 paint/invalidation/position/invalidate-paint-for-fixed-pos-inside-iframe.html [ Failure ] +crbug.com/591099 paint/invalidation/position/invalidate-paint-for-fixed-pos-inside-iframe.html [ Failure Pass ] crbug.com/591099 paint/invalidation/position/justify-content-position-change-grid.html [ Failure ] crbug.com/591099 paint/invalidation/position/justify-content-position-change.html [ Failure ] crbug.com/591099 paint/invalidation/position/layout-state-only-positioned.html [ Failure ] @@ -8114,7 +8107,7 @@ crbug.com/591099 paint/invalidation/position/positioned-list-offset-change-repaint.html [ Failure ] crbug.com/591099 paint/invalidation/position/relative-inline-positioned-movement-repaint.html [ Crash Failure ] crbug.com/591099 paint/invalidation/position/relative-margin-change-repaint.html [ Failure ] -crbug.com/591099 paint/invalidation/position/relative-positioned-movement-repaint.html [ Failure ] +crbug.com/591099 paint/invalidation/position/relative-positioned-movement-repaint.html [ Failure Pass ] crbug.com/591099 paint/invalidation/position/relayout-fixed-position-after-scale.html [ Failure ] crbug.com/591099 paint/invalidation/position/shift-relative-positioned-container-with-image-addition.html [ Failure ] crbug.com/591099 paint/invalidation/position/shift-relative-positioned-container-with-image-removal.html [ Failure ] @@ -8125,7 +8118,7 @@ crbug.com/591099 paint/invalidation/position/transform-relative-position.html [ Failure ] crbug.com/591099 paint/invalidation/push-block-with-first-line.html [ Failure ] crbug.com/591099 paint/invalidation/quotes.html [ Failure ] -crbug.com/591099 paint/invalidation/raster-under-invalidation-checking.html [ Failure ] +crbug.com/591099 paint/invalidation/raster-under-invalidation-checking.html [ Failure Pass ] crbug.com/591099 paint/invalidation/reflection/reflection-invalidation-after-display.html [ Failure ] crbug.com/591099 paint/invalidation/reflection/reflection-invalidation-positioned-child.html [ Failure ] crbug.com/591099 paint/invalidation/reflection/reflection-redraw.html [ Failure ] @@ -8139,10 +8132,10 @@ crbug.com/591099 paint/invalidation/renderer-destruction-by-invalidateSelection-crash.html [ Failure ] crbug.com/714962 paint/invalidation/repaint-across-writing-mode-boundary.html [ Failure ] crbug.com/591099 paint/invalidation/repaint-descandant-on-ancestor-layer-move.html [ Failure ] -crbug.com/591099 paint/invalidation/repaint-in-iframe.html [ Failure ] -crbug.com/591099 paint/invalidation/repaint-on-style-change.html [ Failure ] +crbug.com/591099 paint/invalidation/repaint-in-iframe.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/repaint-on-style-change.html [ Failure Pass ] crbug.com/591099 paint/invalidation/repaint-overlay/layers-overlay.html [ Failure ] -crbug.com/591099 paint/invalidation/repaint-overlay/layers.html [ Failure ] +crbug.com/591099 paint/invalidation/repaint-overlay/layers.html [ Failure Pass ] crbug.com/591099 paint/invalidation/repaint-subrect-grid.html [ Failure ] crbug.com/591099 paint/invalidation/requestAnimation-translation-leave-traces.html [ Failure ] crbug.com/591099 paint/invalidation/resize-iframe-text.html [ Failure ] @@ -8150,44 +8143,44 @@ crbug.com/714962 paint/invalidation/scroll/caret-invalidation-in-overflow-scroll.html [ Failure ] crbug.com/591099 paint/invalidation/scroll/caret-with-composited-scroll.html [ Failure ] crbug.com/591099 paint/invalidation/scroll/composited-add-resizer.html [ Failure ] -crbug.com/591099 paint/invalidation/scroll/composited-iframe-scroll-repaint.html [ Failure ] +crbug.com/591099 paint/invalidation/scroll/composited-iframe-scroll-repaint.html [ Failure Pass ] crbug.com/591099 paint/invalidation/scroll/destroy-composited-scrollbar.html [ Failure ] crbug.com/591099 paint/invalidation/scroll/destroy-overlay-scrollbar.html [ Failure ] crbug.com/591099 paint/invalidation/scroll/destroy-scrollbar.html [ Failure ] crbug.com/591099 paint/invalidation/scroll/fixed-after-scroll.html [ Failure ] crbug.com/591099 paint/invalidation/scroll/fixed-and-absolute-position-scrolled.html [ Failure ] -crbug.com/591099 paint/invalidation/scroll/fixed-child-move-after-scroll.html [ Failure ] -crbug.com/591099 paint/invalidation/scroll/fixed-child-of-fixed-move-after-scroll.html [ Failure ] +crbug.com/591099 paint/invalidation/scroll/fixed-child-move-after-scroll.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/scroll/fixed-child-of-fixed-move-after-scroll.html [ Failure Pass ] crbug.com/591099 paint/invalidation/scroll/fixed-child-of-transformed-move-after-scroll.html [ Failure ] -crbug.com/591099 paint/invalidation/scroll/fixed-child-of-transformed-scrolled.html [ Failure ] -crbug.com/591099 paint/invalidation/scroll/fixed-descendant-of-transformed-scrolled.html [ Failure ] +crbug.com/591099 paint/invalidation/scroll/fixed-child-of-transformed-scrolled.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/scroll/fixed-descendant-of-transformed-scrolled.html [ Failure Pass ] crbug.com/714962 paint/invalidation/scroll/fixed-img-src-change-after-scroll.html [ Failure ] -crbug.com/591099 paint/invalidation/scroll/fixed-move-after-scroll.html [ Failure ] +crbug.com/591099 paint/invalidation/scroll/fixed-move-after-scroll.html [ Failure Pass ] crbug.com/591099 paint/invalidation/scroll/fixed-scroll-simple.html [ Failure ] crbug.com/591099 paint/invalidation/scroll/fixed-under-composited-absolute-scrolled.html [ Crash ] crbug.com/591099 paint/invalidation/scroll/fixed-under-composited-fixed-scrolled.html [ Failure ] crbug.com/591099 paint/invalidation/scroll/fixed-with-border-under-composited-absolute-scrolled.html [ Crash ] -crbug.com/591099 paint/invalidation/scroll/flipped-blocks-writing-mode-scroll.html [ Failure ] +crbug.com/591099 paint/invalidation/scroll/flipped-blocks-writing-mode-scroll.html [ Failure Pass ] crbug.com/591099 paint/invalidation/scroll/iframe-scroll-repaint.html [ Failure ] crbug.com/714962 paint/invalidation/scroll/iframe-scrollbar-hover.html [ Failure ] crbug.com/591099 paint/invalidation/scroll/inline-style-change-in-scrolled-view.html [ Failure ] crbug.com/591099 paint/invalidation/scroll/invalidate-after-composited-scroll-of-window.html [ Failure ] -crbug.com/591099 paint/invalidation/scroll/invalidate-after-composited-scroll.html [ Failure ] +crbug.com/591099 paint/invalidation/scroll/invalidate-after-composited-scroll.html [ Failure Pass ] crbug.com/714962 paint/invalidation/scroll/invalidate-caret-in-composited-scrolling-container.html [ Failure ] crbug.com/714962 paint/invalidation/scroll/invalidate-caret-in-non-composited-scrolling-container.html [ Failure ] crbug.com/591099 paint/invalidation/scroll/layout-state-scrolloffset.html [ Failure ] crbug.com/591099 paint/invalidation/scroll/layout-state-scrolloffset2.html [ Failure ] crbug.com/591099 paint/invalidation/scroll/layout-state-scrolloffset3.html [ Failure ] crbug.com/591099 paint/invalidation/scroll/line-in-scrolled-clipped-block.html [ Failure ] -crbug.com/591099 paint/invalidation/scroll/nested-fixed-iframe-scrolled.html [ Failure ] +crbug.com/591099 paint/invalidation/scroll/nested-fixed-iframe-scrolled.html [ Failure Pass ] crbug.com/591099 paint/invalidation/scroll/outline-change-in-scrollers.html [ Failure ] crbug.com/591099 paint/invalidation/scroll/outline-change-scrollable.html [ Failure ] crbug.com/591099 paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled.html [ Failure ] -crbug.com/591099 paint/invalidation/scroll/overflow-hidden-in-overflow-hidden-scrolled.html [ Failure ] +crbug.com/591099 paint/invalidation/scroll/overflow-hidden-in-overflow-hidden-scrolled.html [ Crash Failure ] crbug.com/591099 paint/invalidation/scroll/overflow-hidden-yet-scrolled-with-custom-scrollbar.html [ Failure ] crbug.com/591099 paint/invalidation/scroll/overflow-hidden-yet-scrolled.html [ Failure ] -crbug.com/591099 paint/invalidation/scroll/overflow-move-after-scroll.html [ Failure ] -crbug.com/591099 paint/invalidation/scroll/overflow-scroll-after-move.html [ Failure ] +crbug.com/591099 paint/invalidation/scroll/overflow-move-after-scroll.html [ Failure Pass ] +crbug.com/591099 paint/invalidation/scroll/overflow-scroll-after-move.html [ Failure Pass ] crbug.com/591099 paint/invalidation/scroll/overflow-scroll-body-appear.html [ Failure ] crbug.com/591099 paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child.html [ Failure ] crbug.com/591099 paint/invalidation/scroll/overflow-scroll-delete.html [ Failure ] @@ -8248,7 +8241,7 @@ crbug.com/591099 paint/invalidation/svg/add-outline-property-on-root.html [ Failure ] crbug.com/714962 paint/invalidation/svg/animate-fill.svg [ Failure ] crbug.com/591099 paint/invalidation/svg/animated-path-inside-transformed-html.xhtml [ Failure Pass ] -crbug.com/591099 paint/invalidation/svg/animated-svg-as-image-transformed-offscreen.html [ Failure ] +crbug.com/591099 paint/invalidation/svg/animated-svg-as-image-transformed-offscreen.html [ Failure Pass ] crbug.com/714962 paint/invalidation/svg/append-text-node-to-tspan.html [ Failure ] crbug.com/714962 paint/invalidation/svg/clip-path-child-changes.svg [ Failure ] crbug.com/714962 paint/invalidation/svg/clip-path-href-changes.svg [ Failure ] @@ -8328,7 +8321,7 @@ crbug.com/714962 paint/invalidation/svg/repaint-non-scaling-stroke-text.html [ Failure ] crbug.com/714962 paint/invalidation/svg/repaint-on-image-bounds-change.svg [ Failure ] crbug.com/714962 paint/invalidation/svg/repaint-paintorder.svg [ Failure ] -crbug.com/591099 paint/invalidation/svg/repaint-svg-after-style-change.html [ Failure ] +crbug.com/591099 paint/invalidation/svg/repaint-svg-after-style-change.html [ Failure Pass ] crbug.com/591099 paint/invalidation/svg/resize-svg-invalidate-children-2.html [ Failure ] crbug.com/591099 paint/invalidation/svg/resize-svg-invalidate-children.html [ Crash Failure ] crbug.com/714962 paint/invalidation/svg/resource-client-removal.svg [ Failure ] @@ -8339,7 +8332,7 @@ crbug.com/714962 paint/invalidation/svg/stroke-opacity-update.svg [ Failure ] crbug.com/591099 paint/invalidation/svg/svg-background-partial-redraw.html [ Failure ] crbug.com/591099 paint/invalidation/svg/svg-image-change-content-size.xhtml [ Failure ] -crbug.com/591099 paint/invalidation/svg/svg-layout-root-style-attr-update.html [ Failure ] +crbug.com/591099 paint/invalidation/svg/svg-layout-root-style-attr-update.html [ Failure Pass ] crbug.com/714962 paint/invalidation/svg/svgsvgelement-repaint-children.html [ Failure ] crbug.com/714962 paint/invalidation/svg/tabgroup.svg [ Failure ] crbug.com/714962 paint/invalidation/svg/text-dom-removal.svg [ Failure ] @@ -8449,9 +8442,9 @@ crbug.com/591099 paint/invalidation/text-shadow.html [ Failure ] crbug.com/714962 paint/invalidation/transform/caret-with-transformation.html [ Failure ] crbug.com/591099 paint/invalidation/transform/change-transform.html [ Failure ] -crbug.com/591099 paint/invalidation/transform/invalidation-with-scale-transform.html [ Failure ] +crbug.com/591099 paint/invalidation/transform/invalidation-with-scale-transform.html [ Failure Pass ] crbug.com/591099 paint/invalidation/transform/resize-skewed.html [ Failure ] -crbug.com/591099 paint/invalidation/transform/rotated-subpixel.html [ Failure ] +crbug.com/591099 paint/invalidation/transform/rotated-subpixel.html [ Failure Pass ] crbug.com/591099 paint/invalidation/transform/subpixel-offset-scaled-transform.html [ Failure ] crbug.com/591099 paint/invalidation/transform/subtree-layoutstate-transform.html [ Failure ] crbug.com/591099 paint/invalidation/transform/transform-disable-layoutstate.html [ Failure ] @@ -8485,27 +8478,27 @@ crbug.com/591099 paint/markers/active-suggestion-marker-split.html [ Failure ] crbug.com/591099 paint/markers/composition-marker-basic.html [ Failure ] crbug.com/591099 paint/markers/composition-marker-split.html [ Failure ] -crbug.com/591099 paint/markers/document-markers-zoom-125.html [ Failure ] -crbug.com/591099 paint/markers/document-markers-zoom-150.html [ Failure ] -crbug.com/591099 paint/markers/document-markers-zoom-175.html [ Failure ] -crbug.com/591099 paint/markers/document-markers-zoom-200.html [ Failure ] -crbug.com/591099 paint/markers/document-markers-zoom-250.html [ Failure ] -crbug.com/591099 paint/markers/document-markers.html [ Failure ] +crbug.com/591099 paint/markers/document-markers-zoom-125.html [ Failure Pass ] +crbug.com/591099 paint/markers/document-markers-zoom-150.html [ Failure Pass ] +crbug.com/591099 paint/markers/document-markers-zoom-175.html [ Failure Pass ] +crbug.com/591099 paint/markers/document-markers-zoom-200.html [ Failure Pass ] +crbug.com/591099 paint/markers/document-markers-zoom-250.html [ Failure Pass ] +crbug.com/591099 paint/markers/document-markers.html [ Failure Pass ] crbug.com/591099 paint/markers/ellipsis-ltr-text-in-ltr-flow-with-markers.html [ Failure ] crbug.com/591099 paint/markers/ellipsis-ltr-text-in-rtl-flow-with-markers.html [ Failure ] crbug.com/591099 paint/markers/ellipsis-mixed-text-in-ltr-flow-with-markers.html [ Failure ] crbug.com/591099 paint/markers/ellipsis-mixed-text-in-rtl-flow-with-markers.html [ Failure ] crbug.com/591099 paint/markers/ellipsis-rtl-text-in-ltr-flow-with-markers.html [ Failure ] crbug.com/591099 paint/markers/ellipsis-rtl-text-in-rtl-flow-with-markers.html [ Failure ] -crbug.com/591099 paint/markers/grammar-markers-hidpi.html [ Failure ] -crbug.com/591099 paint/markers/grammar-markers.html [ Failure ] +crbug.com/591099 paint/markers/grammar-markers-hidpi.html [ Failure Pass ] +crbug.com/591099 paint/markers/grammar-markers.html [ Failure Pass ] crbug.com/591099 paint/markers/inline-spelling-markers-hidpi-composited.html [ Failure ] crbug.com/591099 paint/markers/inline-spelling-markers-hidpi.html [ Crash Failure ] crbug.com/591099 paint/markers/inline_spelling_markers.html [ Failure ] crbug.com/591099 paint/markers/marker-early-break-bug.html [ Failure ] crbug.com/591099 paint/markers/suggestion-marker-basic.html [ Failure ] crbug.com/591099 paint/markers/suggestion-marker-split.html [ Failure ] -crbug.com/591099 paint/masks/fieldset-mask.html [ Failure ] +crbug.com/591099 paint/masks/fieldset-mask.html [ Failure Pass ] crbug.com/591099 paint/overflow/composited-rounded-clip-floating-element.html [ Failure ] crbug.com/591099 paint/overflow/fixed-background-scroll-window.html [ Failure ] crbug.com/591099 paint/overflow/non-composited-fixed-position-descendant.html [ Failure ] @@ -8514,8 +8507,7 @@ crbug.com/591099 paint/printing/print-box-shadow.html [ Failure ] crbug.com/591099 paint/printing/print-text-shadow.html [ Failure ] crbug.com/591099 paint/roundedrects/circle-with-shadow.html [ Failure ] -crbug.com/591099 paint/roundedrects/input-with-rounded-rect-and-shadow.html [ Failure ] -crbug.com/714962 paint/selection/text-selection-counter.html [ Failure Pass ] +crbug.com/591099 paint/roundedrects/input-with-rounded-rect-and-shadow.html [ Failure Pass ] crbug.com/714962 paint/selection/text-selection-drag.html [ Failure ] crbug.com/591099 paint/selection/text-selection-inline-block-rtl.html [ Crash Failure ] crbug.com/591099 paint/selection/text-selection-inline-block.html [ Crash Failure ] @@ -8532,15 +8524,15 @@ crbug.com/591099 paint/selection/text-selection-newline-vertical-rl.html [ Failure ] crbug.com/591099 paint/selection/text-selection-newline.html [ Failure ] crbug.com/714962 paint/selection/text-selection-update-style.html [ Failure ] -crbug.com/591099 paint/selection/text-selection-with-composition.html [ Failure ] -crbug.com/591099 paint/subpixel/transform-inside-clip.html [ Failure ] +crbug.com/591099 paint/selection/text-selection-with-composition.html [ Failure Pass ] +crbug.com/591099 paint/subpixel/transform-inside-clip.html [ Failure Pass ] crbug.com/591099 paint/tables/collapsed-border-corner-conflict.html [ Failure ] crbug.com/591099 paint/tables/composited-collapsed-table-borders.html [ Failure ] crbug.com/591099 paint/text/selection-no-clip-text.html [ Failure ] crbug.com/714962 paint/text/text-match-highlights-big-line-height.html [ Failure ] -crbug.com/591099 paint/theme/adjust-progress-bar-size.html [ Failure ] -crbug.com/591099 paint/transforms/percentage-transform-fractional-box-size.html [ Failure ] -crbug.com/591099 paint/transparency/compositing-alpha-fold-crash.html [ Failure ] +crbug.com/591099 paint/theme/adjust-progress-bar-size.html [ Failure Pass ] +crbug.com/591099 paint/transforms/percentage-transform-fractional-box-size.html [ Failure Pass ] +crbug.com/591099 paint/transparency/compositing-alpha-fold-crash.html [ Failure Pass ] crbug.com/591099 payments/payment-request-in-iframe-nested-not-allowed.html [ Failure ] crbug.com/591099 payments/payment-request-in-iframe.html [ Failure ] crbug.com/591099 plugins/change-widget-and-click-crash.html [ Failure Pass ] @@ -8553,8 +8545,8 @@ crbug.com/591099 plugins/tabindex.html [ Failure ] crbug.com/591099 plugins/webview-plugin-lifecycle.html [ Failure ] crbug.com/591099 plugins/webview-plugin-nested-iframe-scroll.html [ Failure ] -crbug.com/591099 plugins/webview-plugin-scroll.html [ Failure ] -crbug.com/591099 plugins/webview-plugin-type-change.html [ Failure ] +crbug.com/591099 plugins/webview-plugin-scroll.html [ Failure Pass ] +crbug.com/591099 plugins/webview-plugin-type-change.html [ Failure Pass ] crbug.com/591099 pointer-lock/pointerlockchange-pointerlockerror-events.html [ Failure ] crbug.com/591099 printing/absolute-position-headers-and-footers.html [ Failure ] crbug.com/591099 printing/absolute-positioned.html [ Failure ] @@ -8600,7 +8592,7 @@ crbug.com/591099 printing/return-from-printing-mode.html [ Failure ] crbug.com/591099 printing/simultaneous-position-float-change.html [ Failure ] crbug.com/591099 printing/single-line-must-not-be-split-into-two-pages.html [ Timeout ] -crbug.com/591099 printing/standards-percentage-heights.html [ Failure ] +crbug.com/591099 printing/standards-percentage-heights.html [ Failure Pass ] crbug.com/591099 printing/subframes-percentage-height.html [ Failure ] crbug.com/591099 printing/tfoot-repeats-at-bottom-of-each-page-multiple-tables.html [ Failure ] crbug.com/591099 printing/tfoot-repeats-at-bottom-of-each-page.html [ Failure ] @@ -8613,7 +8605,7 @@ crbug.com/591099 scrollbars/custom-scrollbar-with-incomplete-style.html [ Failure ] crbug.com/714962 scrollbars/custom-scrollbars-paint-outside-iframe.html [ Failure ] crbug.com/714962 scrollbars/disabled-scrollbar.html [ Failure ] -crbug.com/714962 scrollbars/overlay-scrollbars-within-overflow-scroll.html [ Failure ] +crbug.com/714962 scrollbars/overlay-scrollbars-within-overflow-scroll.html [ Failure Pass ] crbug.com/714962 scrollbars/resize-scales-with-dpi-150.html [ Failure ] crbug.com/714962 scrollbars/scrollbar-buttons.html [ Failure ] crbug.com/591099 scrollbars/scrollbar-click-does-not-blur-content.html [ Failure ] @@ -8712,9 +8704,9 @@ crbug.com/714962 svg/W3C-SVG-1.1/text-text-06-t.svg [ Failure ] crbug.com/591099 svg/as-background-image/animated-svg-as-background.html [ Crash Failure ] crbug.com/591099 svg/as-background-image/background-image-preserveaspectRatio-support.html [ Failure ] -crbug.com/591099 svg/as-background-image/background-image-tiled.html [ Failure ] +crbug.com/591099 svg/as-background-image/background-image-tiled.html [ Failure Pass ] crbug.com/591099 svg/as-background-image/background-repeat.html [ Failure ] -crbug.com/591099 svg/as-background-image/same-image-two-instances-background-image.html [ Failure ] +crbug.com/591099 svg/as-background-image/same-image-two-instances-background-image.html [ Failure Pass ] crbug.com/591099 svg/as-background-image/svg-as-background-1.html [ Failure ] crbug.com/591099 svg/as-background-image/svg-as-background-2.html [ Failure ] crbug.com/591099 svg/as-background-image/svg-as-background-3.html [ Failure ] @@ -8741,10 +8733,10 @@ crbug.com/714962 svg/as-image/svg-intrinsic-size-rectangular-vertical.html [ Failure ] crbug.com/714962 svg/as-image/svg-intrinsic-size-rectangular.html [ Failure ] crbug.com/591099 svg/as-image/svg-non-integer-scaled-image.html [ Failure ] -crbug.com/591099 svg/as-image/svg-object-intrinsic-size.html [ Failure ] +crbug.com/591099 svg/as-image/svg-object-intrinsic-size.html [ Failure Pass ] crbug.com/591099 svg/as-image/svgview-references-use-counters.html [ Failure ] crbug.com/591099 svg/as-object/object-box-sizing-no-width-height.html [ Failure ] -crbug.com/591099 svg/as-object/svg-embedded-in-html-in-iframe.html [ Failure ] +crbug.com/591099 svg/as-object/svg-embedded-in-html-in-iframe.html [ Failure Pass ] crbug.com/714962 svg/batik/filters/feTile.svg [ Failure ] crbug.com/714962 svg/batik/filters/filterRegions.svg [ Failure ] crbug.com/714962 svg/batik/masking/maskRegions.svg [ Failure ] @@ -8773,8 +8765,8 @@ crbug.com/714962 svg/batik/text/textStyles.svg [ Failure ] crbug.com/714962 svg/batik/text/verticalText.svg [ Failure ] crbug.com/714962 svg/batik/text/verticalTextOnPath.svg [ Failure ] -crbug.com/591099 svg/canvas/canvas-default-object-sizing.html [ Failure ] -crbug.com/591099 svg/canvas/canvas-draw-image-globalalpha.html [ Failure ] +crbug.com/591099 svg/canvas/canvas-default-object-sizing.html [ Failure Pass ] +crbug.com/591099 svg/canvas/canvas-draw-image-globalalpha.html [ Failure Pass ] crbug.com/714962 svg/canvas/canvas-pattern-svg.html [ Failure ] crbug.com/714962 svg/carto.net/scrollbar.svg [ Failure ] crbug.com/714962 svg/carto.net/textbox.svg [ Failure ] @@ -8805,7 +8797,7 @@ crbug.com/714962 svg/clip-path/clip-path-pixelation.svg [ Failure ] crbug.com/714962 svg/clip-path/clip-path-prefixed-vs-not.html [ Failure ] crbug.com/714962 svg/clip-path/clip-path-shape-ellipse-2.svg [ Failure ] -crbug.com/714962 svg/clip-path/clip-path-text-and-shape.svg [ Failure ] +crbug.com/714962 svg/clip-path/clip-path-text-and-shape.svg [ Crash Failure ] crbug.com/714962 svg/clip-path/clip-path-text-and-stroke.svg [ Failure ] crbug.com/714962 svg/clip-path/clip-path-text.svg [ Failure ] crbug.com/714962 svg/clip-path/clip-path-transform-1.svg [ Failure ] @@ -8817,6 +8809,7 @@ crbug.com/714962 svg/clip-path/clip-path-use-as-child4.svg [ Failure ] crbug.com/714962 svg/clip-path/clip-path-use-referencing-clipped-text.html [ Failure ] crbug.com/714962 svg/clip-path/clip-path-use-referencing-text.html [ Failure ] +crbug.com/591099 svg/clip-path/clip-path-use-xy-properties.html [ Failure ] crbug.com/714962 svg/clip-path/clip-path-userSpaceOnUse.svg [ Crash Failure ] crbug.com/714962 svg/clip-path/clip-path-visible-element-as-visible-shape-element.html [ Failure ] crbug.com/714962 svg/clip-path/clip-path-w-broken-filter-on-shape.html [ Failure ] @@ -8833,16 +8826,16 @@ crbug.com/714962 svg/clip-path/nested-clip-in-mask-path-and-image-based-clipping.svg [ Crash Failure ] crbug.com/714962 svg/clip-path/nested-clip-in-mask-path-based-clipping.svg [ Failure ] crbug.com/714962 svg/clip-path/nested-empty-clip.html [ Crash Failure ] -crbug.com/714962 svg/clip-path/opacity-assertion.svg [ Failure ] +crbug.com/714962 svg/clip-path/opacity-assertion.svg [ Crash Failure ] crbug.com/714962 svg/clip-path/transformed-clip.svg [ Failure ] crbug.com/714962 svg/clip-path/visible-clip-path-as-hidden-use-element.html [ Failure ] crbug.com/714962 svg/clip-path/visible-nested-clip-path-as-hidden-use-element.html [ Failure ] -crbug.com/591099 svg/css/background-image-svg.html [ Failure ] +crbug.com/591099 svg/css/background-image-svg.html [ Failure Pass ] crbug.com/591099 svg/css/css-box-min-width.html [ Failure ] crbug.com/591099 svg/css/max-height.html [ Failure ] crbug.com/591099 svg/css/max-width.html [ Failure ] crbug.com/591099 svg/css/text-shadow-multiple.xhtml [ Failure ] -crbug.com/591099 svg/custom/absolute-root-position-masking.xhtml [ Failure ] +crbug.com/591099 svg/custom/absolute-root-position-masking.xhtml [ Failure Pass ] crbug.com/591099 svg/custom/absolute-sized-svg-in-xhtml.xhtml [ Failure ] crbug.com/591099 svg/custom/anchor-on-use.svg [ Failure ] crbug.com/591099 svg/custom/bug45331.svg [ Failure ] @@ -8858,15 +8851,15 @@ crbug.com/591099 svg/custom/dominant-baseline-hanging.svg [ Failure ] crbug.com/591099 svg/custom/elementTimeControl-nan-crash.html [ Failure ] crbug.com/591099 svg/custom/embedding-external-svgs.xhtml [ Failure ] -crbug.com/591099 svg/custom/external-paintserver-reference.svg [ Failure ] -crbug.com/591099 svg/custom/filter-css-transform-resolution.html [ Failure ] +crbug.com/591099 svg/custom/external-paintserver-reference.svg [ Failure Pass ] +crbug.com/591099 svg/custom/filter-css-transform-resolution.html [ Failure Pass ] crbug.com/714962 svg/custom/focus-ring.svg [ Failure ] crbug.com/591099 svg/custom/foreign-object-skew.svg [ Failure ] crbug.com/591099 svg/custom/getscreenctm-in-mixed-content.xhtml [ Failure ] crbug.com/591099 svg/custom/getscreenctm-in-mixed-content2.xhtml [ Failure ] crbug.com/591099 svg/custom/getscreenctm-in-scrollable-div-area-nested.xhtml [ Failure ] crbug.com/591099 svg/custom/getscreenctm-in-scrollable-div-area.xhtml [ Failure ] -crbug.com/591099 svg/custom/getscreenctm-in-scrollable-svg-area.xhtml [ Failure ] +crbug.com/591099 svg/custom/getscreenctm-in-scrollable-svg-area.xhtml [ Failure Pass ] crbug.com/591099 svg/custom/getsvgdocument.html [ Failure ] crbug.com/714962 svg/custom/group-opacity.svg [ Failure ] crbug.com/591099 svg/custom/hit-test-path-stroke.svg [ Failure ] @@ -8889,7 +8882,7 @@ crbug.com/591099 svg/custom/mouse-move-on-svg-container.xhtml [ Timeout ] crbug.com/591099 svg/custom/mouse-move-on-svg-root.xhtml [ Timeout ] crbug.com/591099 svg/custom/no-inherited-dashed-stroke.xhtml [ Failure ] -crbug.com/591099 svg/custom/object-no-size-attributes.xhtml [ Failure ] +crbug.com/591099 svg/custom/object-no-size-attributes.xhtml [ Failure Pass ] crbug.com/591099 svg/custom/object-sizing-explicit-height.xhtml [ Failure ] crbug.com/591099 svg/custom/object-sizing-explicit-width-height.xhtml [ Failure ] crbug.com/591099 svg/custom/object-sizing-explicit-width.xhtml [ Failure ] @@ -8913,7 +8906,7 @@ crbug.com/591099 svg/custom/tabindex-order.html [ Failure ] crbug.com/714962 svg/custom/text-clip.svg [ Failure ] crbug.com/591099 svg/custom/text-match-highlight.html [ Failure ] -crbug.com/591099 svg/custom/text-zoom.xhtml [ Failure ] +crbug.com/591099 svg/custom/text-zoom.xhtml [ Failure Pass ] crbug.com/714962 svg/custom/transformed-outlines.svg [ Failure ] crbug.com/591099 svg/custom/transformed-text-pattern.html [ Failure ] crbug.com/591099 svg/custom/tref-with-progress-tag-setpseudo-assert.html [ Failure ] @@ -8939,7 +8932,7 @@ crbug.com/591099 svg/custom/viewport-em.svg [ Failure ] crbug.com/714962 svg/custom/visibility-override-clip.svg [ Failure ] crbug.com/714962 svg/custom/width-full-percentage.svg [ Failure ] -crbug.com/591099 svg/custom/xhtml-no-svg-renderer.xhtml [ Failure ] +crbug.com/591099 svg/custom/xhtml-no-svg-renderer.xhtml [ Failure Pass ] crbug.com/714962 svg/dom/SVGStringList-basics.xhtml [ Failure ] crbug.com/591099 svg/dom/svg-root-lengths.html [ Failure ] crbug.com/591099 svg/dom/tooltip-title-inline-svg.html [ Failure ] @@ -8956,13 +8949,13 @@ crbug.com/714962 svg/dynamic-updates/SVGMaskElement-svgdom-width-prop.html [ Failure ] crbug.com/714962 svg/dynamic-updates/SVGMaskElement-svgdom-x-prop.html [ Failure ] crbug.com/714962 svg/dynamic-updates/SVGMaskElement-svgdom-y-prop.html [ Failure ] -crbug.com/591099 svg/filters/feBlend-all-modes.html [ Failure ] +crbug.com/591099 svg/filters/feBlend-all-modes.html [ Failure Pass ] crbug.com/591099 svg/filters/feTurbulence-bad-seeds.html [ Crash Failure ] crbug.com/714962 svg/filters/filter-clip.svg [ Failure ] crbug.com/714962 svg/filters/filter-huge-clamping.svg [ Failure ] crbug.com/591099 svg/foreign-object-under-shadow-root-under-hidden.html [ Failure ] crbug.com/591099 svg/foreignObject/background-render-phase.html [ Failure ] -crbug.com/591099 svg/foreignObject/body-background.svg [ Failure ] +crbug.com/591099 svg/foreignObject/body-background.svg [ Failure Pass ] crbug.com/591099 svg/foreignObject/clip.html [ Failure ] crbug.com/591099 svg/foreignObject/fO-parent-display-changes.svg [ Failure ] crbug.com/591099 svg/foreignObject/filter.html [ Failure ] @@ -8989,8 +8982,8 @@ crbug.com/591099 svg/hixie/error/013.xml [ Failure ] crbug.com/591099 svg/hixie/intrinsic/003.html [ Failure ] crbug.com/591099 svg/hixie/mixed/003.xml [ Failure ] -crbug.com/591099 svg/hixie/mixed/004.xml [ Failure ] -crbug.com/591099 svg/hixie/mixed/005.xml [ Failure ] +crbug.com/591099 svg/hixie/mixed/004.xml [ Failure Pass ] +crbug.com/591099 svg/hixie/mixed/005.xml [ Failure Pass ] crbug.com/591099 svg/hixie/mixed/006.xml [ Failure ] crbug.com/591099 svg/hixie/mixed/007.xml [ Failure ] crbug.com/591099 svg/hixie/mixed/008.xml [ Failure ] @@ -9020,25 +9013,25 @@ crbug.com/591099 svg/parser/whitespace-length-invalid-3.html [ Pass Timeout ] crbug.com/591099 svg/parser/whitespace-length-invalid-4.html [ Pass Timeout ] crbug.com/591099 svg/parser/whitespace-number.html [ Timeout ] -crbug.com/591099 svg/stroke/empty-path.html [ Failure ] +crbug.com/591099 svg/stroke/empty-path.html [ Failure Pass ] crbug.com/591099 svg/text/bbox-with-glyph-overflow-on-path.html [ Failure ] crbug.com/591099 svg/text/bbox-with-glyph-overflow-zoomed.html [ Failure ] crbug.com/591099 svg/text/bbox-with-glyph-overflow.html [ Failure ] crbug.com/714962 svg/text/columns-do-not-apply.html [ Failure ] -crbug.com/591099 svg/text/combining-character-queries.html [ Failure ] +crbug.com/591099 svg/text/combining-character-queries.html [ Failure Pass ] crbug.com/591099 svg/text/foreignObject-repaint.xml [ Failure ] crbug.com/591099 svg/text/foreignObject-text-clipping-bug.xml [ Failure ] crbug.com/714962 svg/text/layout-inline-children-assert.html [ Failure ] -crbug.com/591099 svg/text/ligature-queries.html [ Failure ] +crbug.com/591099 svg/text/ligature-queries.html [ Failure Pass ] crbug.com/591099 svg/text/scaling-font-with-geometric-precision.html [ Failure ] crbug.com/714962 svg/text/select-text-svgfont.html [ Failure ] -crbug.com/591099 svg/text/selection-background-color.xhtml [ Failure ] +crbug.com/591099 svg/text/selection-background-color.xhtml [ Failure Pass ] crbug.com/591099 svg/text/selection-dragging-outside-1.html [ Failure ] crbug.com/591099 svg/text/selection-dragging-outside-2.html [ Failure ] crbug.com/591099 svg/text/selection-dragging-outside-3.html [ Failure ] -crbug.com/591099 svg/text/selection-styles.xhtml [ Failure ] +crbug.com/591099 svg/text/selection-styles.xhtml [ Failure Pass ] crbug.com/591099 svg/text/small-fonts-in-html5.html [ Failure ] -crbug.com/591099 svg/text/surrogate-pair-queries.html [ Failure ] +crbug.com/591099 svg/text/surrogate-pair-queries.html [ Failure Pass ] crbug.com/714962 svg/text/text-outline-2.html [ Failure ] crbug.com/591099 svg/text/text-repaint-rects.xhtml [ Failure ] crbug.com/714962 svg/text/text-selection-align-01-b.svg [ Failure ] @@ -9056,11 +9049,11 @@ crbug.com/591099 svg/wicd/test-rightsizing-b.xhtml [ Failure ] crbug.com/591099 svg/wicd/test-scalable-background-image1.xhtml [ Crash Failure ] crbug.com/591099 svg/wicd/test-scalable-background-image2.xhtml [ Failure ] -crbug.com/591099 svg/zoom/page/zoom-background-image-tiled.html [ Failure ] +crbug.com/591099 svg/zoom/page/zoom-background-image-tiled.html [ Failure Pass ] crbug.com/591099 svg/zoom/page/zoom-background-images.html [ Failure ] crbug.com/591099 svg/zoom/page/zoom-clip-path.html [ Failure ] crbug.com/714962 svg/zoom/page/zoom-coords-viewattr-01-b.svg [ Failure ] -crbug.com/591099 svg/zoom/page/zoom-foreign-content.svg [ Failure ] +crbug.com/591099 svg/zoom/page/zoom-foreign-content.svg [ Failure Pass ] crbug.com/591099 svg/zoom/page/zoom-foreignObject.svg [ Failure ] crbug.com/591099 svg/zoom/page/zoom-hixie-mixed-008.xml [ Failure ] crbug.com/591099 svg/zoom/page/zoom-hixie-mixed-009.xml [ Failure ] @@ -9397,7 +9390,7 @@ crbug.com/591099 transforms/2d/transform-fixed-container.html [ Failure ] crbug.com/591099 transforms/2d/transform-origin-borderbox.html [ Failure ] crbug.com/591099 transforms/2d/zoom-menulist.html [ Failure ] -crbug.com/591099 transforms/3d/general/background-visibility-layers.html [ Failure ] +crbug.com/591099 transforms/3d/general/background-visibility-layers.html [ Failure Pass ] crbug.com/591099 transforms/3d/general/cssmatrix-3d-zoom.html [ Failure ] crbug.com/591099 transforms/3d/general/matrix-with-zoom-3d.html [ Failure ] crbug.com/591099 transforms/3d/general/perspective-non-layer.html [ Failure ] @@ -9420,7 +9413,7 @@ crbug.com/591099 transforms/matrix-01.html [ Failure ] crbug.com/591099 transforms/matrix-02.html [ Failure ] crbug.com/591099 transforms/matrix-with-zoom.html [ Failure ] -crbug.com/591099 transforms/mirror-transform-tiled-scaled-background.html [ Failure ] +crbug.com/591099 transforms/mirror-transform-tiled-scaled-background.html [ Failure Pass ] crbug.com/591099 transforms/overflow-with-transform.html [ Failure ] crbug.com/591099 transforms/rotated-transform-affects-scrolling-1.html [ Failure ] crbug.com/591099 transforms/rotated-transform-affects-scrolling-2.html [ Failure ] @@ -9439,8 +9432,8 @@ crbug.com/591099 transforms/transforms-with-opacity.html [ Failure ] crbug.com/591099 transforms/transforms-with-zoom.html [ Failure ] crbug.com/591099 transitions/opacity-transform-transitions-inside-iframe.html [ Failure ] -crbug.com/591099 transitions/opacity-transition-zindex.html [ Failure ] -crbug.com/591099 transitions/transition-end-event-rendering.html [ Failure ] +crbug.com/591099 transitions/opacity-transition-zindex.html [ Failure Pass ] +crbug.com/591099 transitions/transition-end-event-rendering.html [ Failure Pass ] crbug.com/591099 traversal/tree-walker-003.html [ Failure ] crbug.com/591099 traversal/tree-walker-004.html [ Failure ] crbug.com/591099 vibration/vibration-iframe.html [ Timeout ] @@ -9491,13 +9484,13 @@ crbug.com/714962 virtual/gpu-rasterization/images/drag-image-transformed-parent.html [ Failure ] crbug.com/591099 virtual/gpu-rasterization/images/embed-does-not-propagate-dimensions-to-object-ancestor.html [ Failure ] crbug.com/591099 virtual/gpu-rasterization/images/exif-orientation-css.html [ Failure ] -crbug.com/591099 virtual/gpu-rasterization/images/exif-orientation-height-image-document.html [ Failure ] +crbug.com/591099 virtual/gpu-rasterization/images/exif-orientation-height-image-document.html [ Failure Pass ] crbug.com/591099 virtual/gpu-rasterization/images/exif-orientation-image-document.html [ Failure ] crbug.com/591099 virtual/gpu-rasterization/images/exif-orientation.html [ Failure ] crbug.com/591099 virtual/gpu-rasterization/images/favicon-as-image.html [ Failure ] crbug.com/591099 virtual/gpu-rasterization/images/gif-loop-count.html [ Failure ] crbug.com/591099 virtual/gpu-rasterization/images/gif-short-app-extension-string.html [ Failure ] -crbug.com/591099 virtual/gpu-rasterization/images/gray-scale-jpeg-with-color-profile.html [ Failure ] +crbug.com/591099 virtual/gpu-rasterization/images/gray-scale-jpeg-with-color-profile.html [ Failure Pass ] crbug.com/591099 virtual/gpu-rasterization/images/gray-scale-png-with-color-profile.html [ Failure ] crbug.com/591099 virtual/gpu-rasterization/images/icon-0colors.html [ Failure ] crbug.com/591099 virtual/gpu-rasterization/images/icon-decoding.html [ Failure ] @@ -9545,13 +9538,13 @@ crbug.com/591099 virtual/gpu-rasterization/images/webp-flip.html [ Failure ] crbug.com/591099 virtual/gpu/fast/canvas/canvas-createImageBitmap-colorClamping.html [ Pass ] crbug.com/591099 virtual/gpu/fast/canvas/canvas-createImageBitmap-drawImage.html [ Timeout ] -crbug.com/714962 virtual/gpu/fast/canvas/canvas-css-clip-path.html [ Failure ] +crbug.com/714962 virtual/gpu/fast/canvas/canvas-css-clip-path.html [ Failure Timeout ] crbug.com/591099 virtual/gpu/fast/canvas/canvas-drawImage-animated-images.html [ Failure ] crbug.com/591099 virtual/gpu/fast/canvas/canvas-drawImage-video-imageSmoothingEnabled.html [ Pass ] -crbug.com/591099 virtual/gpu/fast/canvas/canvas-ellipse-connecting-line.html [ Failure ] +crbug.com/591099 virtual/gpu/fast/canvas/canvas-ellipse-connecting-line.html [ Failure Pass ] crbug.com/591099 virtual/gpu/fast/canvas/canvas-imageSmoothingQuality.html [ Pass ] crbug.com/591099 virtual/gpu/fast/canvas/canvas-measure-bidi-text.html [ Failure ] -crbug.com/591099 virtual/gpu/fast/canvas/canvas-render-layer.html [ Failure ] +crbug.com/591099 virtual/gpu/fast/canvas/canvas-render-layer.html [ Failure Pass ] crbug.com/591099 virtual/gpu/fast/canvas/canvas-shadow-source-in.html [ Crash Failure Timeout ] crbug.com/714962 virtual/gpu/fast/canvas/canvas-text-ideographic-space.html [ Failure ] crbug.com/714962 virtual/gpu/fast/canvas/canvas-textMetrics-width.html [ Failure ] @@ -9574,6 +9567,7 @@ crbug.com/714962 virtual/incremental-shadow-dom/fast/dom/shadow/hover-active-drag-distributed-nodes.html [ Failure ] crbug.com/714962 virtual/incremental-shadow-dom/fast/dom/shadow/import-rule-in-shadow-tree-needs-document-style-recalc.html [ Failure ] crbug.com/714962 virtual/incremental-shadow-dom/fast/dom/shadow/input-color-in-content.html [ Timeout ] +crbug.com/591099 virtual/incremental-shadow-dom/fast/dom/shadow/no-renderers-for-light-children.html [ Pass ] crbug.com/714962 virtual/incremental-shadow-dom/fast/dom/shadow/scrollbar.html [ Crash ] crbug.com/714962 virtual/incremental-shadow-dom/fast/dom/shadow/select-in-shadowdom.html [ Failure ] crbug.com/591099 virtual/incremental-shadow-dom/fast/dom/shadow/selections-in-shadow.html [ Timeout ] @@ -9647,7 +9641,6 @@ crbug.com/591099 virtual/mouseevent_fractional/fast/events/domactivate-sets-underlying-click-event-as-handled.html [ Crash ] crbug.com/714962 virtual/mouseevent_fractional/fast/events/drag-and-drop-subframe-dataTransfer.html [ Timeout ] crbug.com/714962 virtual/mouseevent_fractional/fast/events/drag-dataTransferItemList-file-handling.html [ Failure ] -crbug.com/591099 virtual/mouseevent_fractional/fast/events/drag-dragend-detaches.html [ Failure Pass ] crbug.com/714962 virtual/mouseevent_fractional/fast/events/drag-in-frames.html [ Failure ] crbug.com/591099 virtual/mouseevent_fractional/fast/events/drag-selects-image.html [ Failure ] crbug.com/591099 virtual/mouseevent_fractional/fast/events/drag_and_drop_into_removed_on_focus.html [ Failure ] @@ -9693,7 +9686,6 @@ crbug.com/591099 virtual/mouseevent_fractional/fast/events/onload-webkit-before-webcore.html [ Failure ] crbug.com/591099 virtual/mouseevent_fractional/fast/events/pointer-events-2.html [ Failure ] crbug.com/714962 virtual/mouseevent_fractional/fast/events/pointerevents/mouse-node-remove.html [ Failure ] -crbug.com/591099 virtual/mouseevent_fractional/fast/events/pointerevents/mouse-on-object.html [ Failure Pass ] crbug.com/714962 virtual/mouseevent_fractional/fast/events/pointerevents/mouse-pointer-boundary-events-for-shadowdom.html [ Failure ] crbug.com/591099 virtual/mouseevent_fractional/fast/events/pointerevents/mouse-pointer-capture-transition-events.html [ Timeout ] crbug.com/591099 virtual/mouseevent_fractional/fast/events/pointerevents/mouse-pointer-capture.html [ Failure Pass Timeout ] @@ -9778,52 +9770,52 @@ crbug.com/591099 virtual/scroll_customization/fast/events/touch/compositor-touch-hit-rects.html [ Failure ] crbug.com/591099 virtual/service-worker-script-streaming/ [ Skip ] crbug.com/591099 virtual/service-worker-script-streaming/external/wpt/service-workers/service-worker/ServiceWorkerGlobalScope/registration-attribute.https.html [ Failure Pass ] -crbug.com/591099 virtual/spv175/compositing/absolute-inside-out-of-view-fixed.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/animation/busy-indicator.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/absolute-inside-out-of-view-fixed.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/animation/busy-indicator.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/animation/state-at-end-event-transform-layer.html [ Failure ] crbug.com/714962 virtual/spv175/compositing/background-color/view-blending-base-background.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/checkerboard.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/checkerboard.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/child-transform-layer-requires-box.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/clip-child-by-non-stacking-ancestor.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/clip-child-by-non-stacking-ancestor.html [ Failure Pass ] crbug.com/714962 virtual/spv175/compositing/clip-path-with-composited-descendent.html [ Pass ] crbug.com/591099 virtual/spv175/compositing/color-matching/image-color-matching.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/columns/composited-in-paginated.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/columns/composited-in-paginated.html [ Failure Pass ] crbug.com/714962 virtual/spv175/compositing/composited-descendant-grandparent-border-radius-mask.html [ Pass ] crbug.com/714962 virtual/spv175/compositing/composited-descendant-requiring-border-radius-mask.html [ Pass ] -crbug.com/591099 virtual/spv175/compositing/composited-scaled-child-with-border-radius-parent-clip.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/composited-translated-child-with-border-radius-parent-clip.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/composited-scaled-child-with-border-radius-parent-clip.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/composited-translated-child-with-border-radius-parent-clip.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/compositing-visible-descendant.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/contents-opaque/background-clip.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/contents-opaque/background-color.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/contents-opaque/background-clip.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/contents-opaque/background-color.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/contents-opaque/body-background-painted.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/contents-opaque/body-background-skipped.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/contents-opaque/filter.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/contents-opaque/hidden-with-visible-child.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/contents-opaque/hidden-with-visible-text.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/contents-opaque/layer-opacity.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/contents-opaque/layer-transform.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/contents-opaque/overflow-hidden-child-layers.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/contents-opaque/filter.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/contents-opaque/hidden-with-visible-child.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/contents-opaque/hidden-with-visible-text.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/contents-opaque/layer-opacity.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/contents-opaque/layer-transform.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/contents-opaque/overflow-hidden-child-layers.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/direct-image-compositing.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/draws-content/canvas-background-layer.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/draws-content/webgl-background-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/filters/sw-layer-overlaps-hw-shadow.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/filters/sw-shadow-overlaps-hw-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/filters/sw-shadow-overlaps-hw-shadow.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/fixed-position-changed-to-absolute.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/filters/sw-layer-overlaps-hw-shadow.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/filters/sw-shadow-overlaps-hw-layer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/filters/sw-shadow-overlaps-hw-shadow.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/fixed-position-changed-to-absolute.html [ Failure Pass ] crbug.com/714962 virtual/spv175/compositing/flex-composited-animated-table-row-background.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/framesets/composited-frame-alignment.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/generated-content.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/geometry/abs-position-inside-opacity.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/geometry/ancestor-overflow-change.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/geometry/bounds-clipped-composited-child.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/geometry/bounds-ignores-hidden-composited-descendant.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/geometry/bounds-ignores-hidden-dynamic-negzindex.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/geometry/ancestor-overflow-change.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/geometry/bounds-clipped-composited-child.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/geometry/bounds-ignores-hidden-composited-descendant.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/geometry/bounds-ignores-hidden-dynamic-negzindex.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/geometry/bounds-ignores-hidden-dynamic.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/geometry/bounds-ignores-hidden.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/geometry/clip-inside.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/geometry/clip-with-shadow.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/geometry/clip.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/geometry/clip-inside.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/geometry/clip-with-shadow.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/geometry/clip.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/geometry/clipping-foreground.html [ Crash Failure ] crbug.com/591099 virtual/spv175/compositing/geometry/composited-html-size.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/geometry/composited-in-columns.html [ Failure ] @@ -9833,27 +9825,27 @@ crbug.com/591099 virtual/spv175/compositing/geometry/fixed-position-transform-composited-page-scale-down.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/geometry/fixed-position-transform-composited-page-scale.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/geometry/fixed-position.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/geometry/flipped-writing-mode.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/geometry/flipped-writing-mode.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/geometry/foreground-layer.html [ Crash Failure ] -crbug.com/591099 virtual/spv175/compositing/geometry/horizontal-scroll-composited.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/geometry/layer-due-to-layer-children-deep-switch.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/geometry/horizontal-scroll-composited.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/geometry/layer-due-to-layer-children-deep-switch.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/geometry/layer-due-to-layer-children-deep.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/geometry/layer-due-to-layer-children-switch.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/geometry/layer-due-to-layer-children-switch.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/geometry/layer-due-to-layer-children.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/geometry/limit-layer-bounds-opacity-transition.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/geometry/limit-layer-bounds-overflow-root.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/geometry/limit-layer-bounds-positioned-transition.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/geometry/limit-layer-bounds-positioned.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/geometry/limit-layer-bounds-transformed.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/geometry/limit-layer-bounds-opacity-transition.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/geometry/limit-layer-bounds-overflow-root.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/geometry/limit-layer-bounds-positioned-transition.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/geometry/limit-layer-bounds-positioned.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/geometry/limit-layer-bounds-transformed.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/geometry/outline-change.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/geometry/partial-layout-update.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/geometry/preserve-3d-switching.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/geometry/preserve-3d-switching.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/geometry/repaint-foreground-layer.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/geometry/root-layer-update.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/geometry/tall-page-composited.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/geometry/tall-page-composited.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/geometry/transformed-abs-position-inside-composited.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/geometry/transfrom-origin-on-zero-size-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/geometry/vertical-scroll-composited.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/geometry/vertical-scroll-composited.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/geometry/video-fixed-scrolling.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/geometry/video-opacity-overlay.html [ Failure ] crbug.com/714962 virtual/spv175/compositing/gestures/gesture-tapHighlight-1-iframe-composited-scrolled-late-composite.html [ Failure ] @@ -9909,90 +9901,90 @@ crbug.com/714962 virtual/spv175/compositing/gestures/gesture-tapHighlight-simple.html [ Crash ] crbug.com/714962 virtual/spv175/compositing/gestures/gesture-tapHighlight-with-box-shadow.html [ Crash ] crbug.com/714962 virtual/spv175/compositing/gestures/gesture-tapHighlight-with-squashing.html [ Crash ] -crbug.com/591099 virtual/spv175/compositing/iframes/become-composited-nested-iframes.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/iframes/become-overlapped-iframe.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/iframes/become-composited-nested-iframes.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/iframes/become-overlapped-iframe.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/iframes/composited-iframe-alignment.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/iframes/composited-iframe-scroll.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/iframes/composited-parent-iframe.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/iframes/connect-compositing-iframe-delayed.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/iframes/connect-compositing-iframe.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/iframes/connect-compositing-iframe2.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/iframes/connect-compositing-iframe3.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/iframes/enter-compositing-iframe.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/iframes/composited-iframe-scroll.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/iframes/composited-parent-iframe.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/iframes/connect-compositing-iframe-delayed.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/iframes/connect-compositing-iframe.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/iframes/connect-compositing-iframe2.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/iframes/connect-compositing-iframe3.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/iframes/enter-compositing-iframe.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/iframes/floating-self-painting-frame.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/iframes/iframe-content-flipping.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/iframes/iframe-content-flipping.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/iframes/iframe-copy-on-scroll.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/iframes/iframe-in-composited-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/iframes/iframe-resize.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/iframes/iframe-size-from-zero.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/iframes/invisible-iframe.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/iframes/invisible-nested-iframe-hide.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/iframes/invisible-nested-iframe-show.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/iframes/invisible-nested-iframe.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/iframes/iframe-resize.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/iframes/iframe-size-from-zero.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/iframes/invisible-iframe.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/iframes/invisible-nested-iframe-hide.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/iframes/invisible-nested-iframe-show.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/iframes/invisible-nested-iframe.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/iframes/layout-on-compositing-change.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/iframes/nested-iframe-scrolling.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/iframes/overlapped-iframe-iframe.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/iframes/overlapped-iframe.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/iframes/overlapped-nested-iframes.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/iframes/resizer.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/iframes/scrolling-iframe.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/iframes/overlapped-iframe-iframe.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/iframes/overlapped-iframe.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/iframes/overlapped-nested-iframes.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/iframes/resizer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/iframes/scrolling-iframe.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/images/direct-image-background-color.html [ Failure ] crbug.com/714962 virtual/spv175/compositing/images/direct-image-dynamic-border-radius.html [ Pass ] crbug.com/591099 virtual/spv175/compositing/images/direct-svg-image.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/img-layer-object-fit.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/animation-overlap-with-children.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/assumed-overlap-for-inline-transform.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-and-transform.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-change-out-of-view-in-view.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-in-fixed-overflow.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-no-content.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-nonscrollable-body-overlap.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/animation-overlap-with-children.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/assumed-overlap-for-inline-transform.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-and-transform.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-change-out-of-view-in-view.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-in-fixed-overflow.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-no-content.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-nonscrollable-body-mismatch-containers.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-nonscrollable-body-overlap.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-nonscrollable-iframes-in-scrollable-page.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-out-of-view-positioning.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-out-of-view-scaled-scroll.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-out-of-view-scaled.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-out-of-view-with-backdrop-filter.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-out-of-view.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-under-transform.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/no-compositing-for-fixed-position-under-transform.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/no-compositing-for-preserve-3d.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/overflow-scroll-overlap.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/overlap-animation-clipping.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/overlap-animation-container.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/overlap-animation.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/overlap-child-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/overlap-clipping.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/overlap-transformed-3d.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/overlap-transformed-and-clipped.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-out-of-view-positioning.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-out-of-view-scaled-scroll.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-out-of-view-scaled.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-out-of-view-with-backdrop-filter.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-out-of-view.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/fixed-position-under-transform.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/no-compositing-for-fixed-position-under-transform.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/no-compositing-for-preserve-3d.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/overflow-scroll-overlap.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/overlap-animation-clipping.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/overlap-animation-container.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/overlap-animation.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/overlap-child-layer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/overlap-clipping.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/overlap-transformed-3d.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/overlap-transformed-and-clipped.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/layer-creation/overlap-transformed-layer-with-transform-body.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/overlap-transformed-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/overlap-transformed-preserved-3d.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/overlap-transforms.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/remove-clipping-layer-with-no-children.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/overlap-transformed-layer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/overlap-transformed-preserved-3d.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/overlap-transforms.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/remove-clipping-layer-with-no-children.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/layer-creation/rotate3d-overlap.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/scroll-partial-update.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/spanOverlapsCanvas.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/stacking-context-overlap-nested.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/stacking-context-overlap.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/translatez-added.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/layer-creation/translatez-overlap.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/scroll-partial-update.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/spanOverlapsCanvas.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/squashing-into-ancestor-clipping-layer-change.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/stacking-context-overlap-nested.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/stacking-context-overlap.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/translatez-added.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/layer-creation/translatez-overlap.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/layers-inside-overflow-scroll.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/lots-of-img-layers-with-opacity.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/lots-of-img-layers.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/lots-of-img-layers-with-opacity.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/lots-of-img-layers.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/masks/direct-image-mask.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/masks/mask-layer-size.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/masks/mask-of-clipped-layer.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/masks/mask-layer-size.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/masks/mask-of-clipped-layer.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/masks/mask-with-added-filters.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/masks/mask-with-removed-filters.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/masks/masked-ancestor.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/masks/multiple-masks.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/masks/simple-composited-mask.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/nested-border-radius-composited-child.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/opacity-with-mask.html [ Failure ] -crbug.com/714962 virtual/spv175/compositing/overflow/absolute-element-in-isolated-composited-ancestor.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/accelerated-overflow-scroll-should-not-affect-perspective.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/nested-border-radius-composited-child.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/opacity-with-mask.html [ Failure Pass ] +crbug.com/714962 virtual/spv175/compositing/overflow/absolute-element-in-isolated-composited-ancestor.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/overflow/accelerated-overflow-scroll-should-not-affect-perspective.html [ Failure Pass ] crbug.com/714962 virtual/spv175/compositing/overflow/accelerated-scrolling-with-clip-reference.html [ Pass ] crbug.com/591099 virtual/spv175/compositing/overflow/ancestor-overflow.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/overflow/border-radius-above-composited-subframe.html [ Failure ] @@ -10001,54 +9993,54 @@ crbug.com/591099 virtual/spv175/compositing/overflow/border-radius-on-parent-composited-grandchild.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/overflow/border-radius-on-squashed-layers.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/overflow/border-radius-on-two-ancestors-composited-grandchild.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/border-radius-outside-bounds-of-compositing-ancestor.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/overflow/border-radius-outside-bounds-of-compositing-ancestor.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/overflow/border-radius-styles-with-composited-child.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/clear-scroll-parent.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/clip-descendents.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/overflow/clear-scroll-parent.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/overflow/clip-descendents.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/overflow/clip-parent-reset.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/clipping-ancestor-with-accelerated-scrolling-ancestor.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/overflow/clipping-ancestor-with-accelerated-scrolling-ancestor.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/overflow/composited-layer-under-border-radius-under-composited-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/composited-scrolling-paint-phases.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/content-gains-scrollbars.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/content-loses-scrollbars.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/overflow/composited-scrolling-paint-phases.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/overflow/content-gains-scrollbars.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/overflow/content-loses-scrollbars.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/overflow/do-not-crash-use-after-free-update-widget-positions.html [ Crash ] -crbug.com/714962 virtual/spv175/compositing/overflow/fixed-element-in-isolated-composited-ancestor.html [ Failure ] +crbug.com/714962 virtual/spv175/compositing/overflow/fixed-element-in-isolated-composited-ancestor.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/overflow/fixed-position-ancestor-clip.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/fractional-sized-scrolling-layer.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/overflow/fractional-sized-scrolling-layer.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/overflow/get-transform-from-non-box-container.html [ Crash ] crbug.com/591099 virtual/spv175/compositing/overflow/grandchild-composited-with-border-radius-ancestor.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/overflow/grandchild-with-border-radius-ancestor.html [ Failure ] crbug.com/714962 virtual/spv175/compositing/overflow/image-load-overflow-scrollbars.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/mask-with-filter.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/overflow/mask-with-filter.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/overflow/mask-with-small-content-rect.html [ Failure ] -crbug.com/714962 virtual/spv175/compositing/overflow/mixed-composited-nested-sticky-overflow-scroller.html [ Failure ] +crbug.com/714962 virtual/spv175/compositing/overflow/mixed-composited-nested-sticky-overflow-scroller.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/overflow/nested-border-radius-clipping.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/nested-render-surfaces-with-intervening-clip.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/nested-render-surfaces-with-rotation.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/nested-render-surfaces.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/overflow/nested-render-surfaces-with-intervening-clip.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/overflow/nested-render-surfaces-with-rotation.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/overflow/nested-render-surfaces.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/overflow/nested-scrolling.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/no-excessive-clip-parent-if-parent-escaped.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/overflow-clip-with-accelerated-scrolling-ancestor.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/overflow/no-excessive-clip-parent-if-parent-escaped.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/overflow/overflow-clip-with-accelerated-scrolling-ancestor.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/overflow/overflow-compositing-descendant.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/overflow/overflow-positioning.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/overflow/overflow-scroll-with-local-image-background.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/overflow/overflow-scroll.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/overflow-scrollbar-layers.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/overflow/overflow-scrollbar-layers.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/overflow/overflow-with-negative-z-index-child.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/overflow/parent-overflow.html [ Failure ] crbug.com/714962 virtual/spv175/compositing/overflow/relpos-under-abspos-border-radius.html [ Pass ] crbug.com/591099 virtual/spv175/compositing/overflow/remove-overflow-crash2.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/reparented-scrollbars-non-sc-anc.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/resize-painting.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/overflow/reparented-scrollbars-non-sc-anc.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/overflow/resize-painting.html [ Failure Pass ] crbug.com/714962 virtual/spv175/compositing/overflow/rtl-overflow.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/overflow/scaled-mask.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/scaled-overflow.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/overflow/scaled-overflow.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/overflow/scroll-ancestor-update.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/scroll-neg-z-index-and-composited-child.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/scroll-parent-absolute-with-backdrop-filter.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/scroll-parent-absolute.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/scrollbar-layer-placement.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/overflow/scroll-neg-z-index-and-composited-child.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/overflow/scroll-parent-absolute-with-backdrop-filter.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/overflow/scroll-parent-absolute.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/overflow/scroll-parent-with-non-stacking-context-composited-ancestor.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/overflow/scrollbar-layer-placement.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/overflow/scrollbar-painting.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/overflow/scrolling-content-clip-to-viewport.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped.html [ Failure ] @@ -10057,20 +10049,20 @@ crbug.com/591099 virtual/spv175/compositing/overflow/textarea-scroll-touch.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/overflow/theme-affects-visual-overflow.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/overflow/tiled-mask.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/universal-accelerated-overflow-scroll.html [ Failure Timeout ] +crbug.com/591099 virtual/spv175/compositing/overflow/universal-accelerated-overflow-scroll.html [ Failure Pass Timeout ] crbug.com/591099 virtual/spv175/compositing/overflow/update-widget-positions-on-nested-frames-and-scrollers.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/overflow/zero-size-overflow.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/overflow/zero-size-overflow.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/overlap-blending/children-opacity-huge.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/overlap-blending/children-opacity-no-overlap.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/overlap-blending/reflection-opacity-huge.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/perspective-interest-rect.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/plugins/webplugin-alpha.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/plugins/webplugin-no-alpha.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/plugins/webplugin-reflection.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/reflections/backface-hidden-reflection.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/perspective-interest-rect.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/plugins/webplugin-alpha.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/plugins/webplugin-no-alpha.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/plugins/webplugin-reflection.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/reflections/backface-hidden-reflection.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/reflections/compositing-change-inside-reflection.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/reflections/deeply-nested-reflections.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/reflections/enable-disable-compositing-reflection.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/reflections/enable-disable-compositing-reflection.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/reflections/load-video-in-reflection.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/reflections/masked-reflection-on-composited.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/reflections/nested-reflection-mask-change.html [ Failure ] @@ -10090,8 +10082,8 @@ crbug.com/591099 virtual/spv175/compositing/reflections/simple-composited-reflections.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/reflections/transform-inside-reflection.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/render-surface-alpha-blending.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/rendering-contexts.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/rounded-corners.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/rendering-contexts.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/rounded-corners.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/rtl/rtl-absolute-overflow-scrolled.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/rtl/rtl-absolute-overflow.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/rtl/rtl-absolute.html [ Failure ] @@ -10105,74 +10097,74 @@ crbug.com/591099 virtual/spv175/compositing/rtl/rtl-iframe-fixed-overflow-scrolled.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/rtl/rtl-iframe-fixed-overflow.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/rtl/rtl-iframe-fixed.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/rtl/rtl-iframe-relative.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/rtl/rtl-iframe-relative.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/rtl/rtl-overflow-invalidation.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/rtl/rtl-overflow-scrolling.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/rtl/rtl-relative.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/rtl/rtl-relative.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/self-painting-layers.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/shadows/shadow-drawing.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/sibling-positioning.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/squashing/add-remove-squashed-layers.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/clipping-ancestor.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/composited-bounds-for-negative-z.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/do-not-squash-non-self-painting-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/dont-squash-into-iframes.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/dont-squash-into-videos.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/iframes-are-never-squashed.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/invalidations-with-large-negative-margin-inline-content.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/invisible-layers-should-not-affect-geometry.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/move-squashing-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/no-squashing-for-filters.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/no-squashing-into-another-clip-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/no-squashing-into-fixed-position-that-clips.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/opacity-squashed-owner.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/repaint-child-of-squashed.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/squashing/clipping-ancestor.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/composited-bounds-for-negative-z.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/do-not-squash-non-self-painting-layer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/dont-squash-into-iframes.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/dont-squash-into-videos.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/iframes-are-never-squashed.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/invalidations-with-large-negative-margin-inline-content.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/invisible-layers-should-not-affect-geometry.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/move-squashing-layer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/no-squashing-for-filters.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/no-squashing-into-another-clip-layer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/no-squashing-into-fixed-position-that-clips.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/opacity-squashed-owner.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/repaint-child-of-squashed.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/squashing/selection-repaint-with-gaps.html [ Crash Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/squash-above-fixed-1.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/squash-above-fixed-2.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/squash-above-fixed-3.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/squash-compositing-hover.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/squashing/squash-above-fixed-1.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/squash-above-fixed-2.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/squash-above-fixed-3.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/squash-compositing-hover.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/squashing/squash-onto-distant-relative.html [ Crash ] -crbug.com/591099 virtual/spv175/compositing/squashing/squash-onto-nephew.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/squash-onto-transform-backing.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/squash-paint-invalidation-fixed-position.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/squash-same-transform-ancestor.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/squash-simple.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/squash-three-layers.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/squash-transform-repainting-child.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/squash-transform-repainting-transformed-child.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/squash-transform.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/squashing/squash-onto-nephew.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/squash-onto-transform-backing.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/squash-paint-invalidation-fixed-position.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/squash-same-transform-ancestor.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/squash-simple.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/squash-three-layers.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/squash-transform-repainting-child.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/squash-transform-repainting-transformed-child.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/squash-transform.html [ Failure Pass ] crbug.com/714962 virtual/spv175/compositing/squashing/squash-with-ancestor-reflection.html [ Pass ] -crbug.com/591099 virtual/spv175/compositing/squashing/squashed-layer-loses-graphicslayer.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/squashed-repaints.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/squashing/squashed-layer-loses-graphicslayer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/squashed-repaints.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/squashing/squashing-does-not-stop-transform-propagation.html [ Crash Pass ] -crbug.com/591099 virtual/spv175/compositing/squashing/squashing-inside-perspective.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/squashing-print.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/squashing/squashing-sparsity-heuristic.html [ Failure ] -crbug.com/714962 virtual/spv175/compositing/squashing/universal-accelerated-overflow-scrolling.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/squashing/squashing-inside-perspective.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/squashing-print.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/squashing/squashing-sparsity-heuristic.html [ Failure Pass ] +crbug.com/714962 virtual/spv175/compositing/squashing/universal-accelerated-overflow-scrolling.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/squashing/vertical-writing-mode-squashed.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/text-on-large-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/tiled-layers-hidpi.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/tiled-layers-hidpi.html [ Failure Pass ] crbug.com/714962 virtual/spv175/compositing/transitions/transform-on-large-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/update-paint-phases.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/update-paint-phases.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/video-frame-size-change.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/video/video-controls-layer-creation.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/visibility/layer-visible-content.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/visibility/visibility-composited-transforms.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/visibility/visibility-composited.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/visibility/visibility-image-layers-dynamic.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/visibility/visibility-on-distant-descendant.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/visibility/layer-visible-content.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/visibility/visibility-composited-transforms.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/visibility/visibility-composited.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/visibility/visibility-image-layers-dynamic.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/compositing/visibility/visibility-on-distant-descendant.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/webgl/webgl-background-color.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/webgl/webgl-nonpremultiplied-blend.html [ Failure ] crbug.com/591099 virtual/spv175/compositing/webgl/webgl-reflection.html [ Failure ] -crbug.com/591099 virtual/spv175/compositing/will-change/composited-layers.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/will-change/composited-layers.html [ Failure Pass ] crbug.com/591099 virtual/spv175/compositing/will-change/will-change-preserve-backface-visibility.html [ Crash Pass ] crbug.com/591099 virtual/spv175/compositing/z-order/collect-layers-does-not-initialize-pos-z-order-list.html [ Crash ] -crbug.com/591099 virtual/spv175/compositing/z-order/negative-z-index.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/background/fieldset-legend-background-shadow-border-radius.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/background/rounded-clip-fractional-offset.html [ Failure ] +crbug.com/591099 virtual/spv175/compositing/z-order/negative-z-index.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/background/fieldset-legend-background-shadow-border-radius.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/background/rounded-clip-fractional-offset.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/filters/clip-filter-overflow-clip.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/filters/clip-under-filter.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/filters/clip-under-filter.html [ Failure Pass ] crbug.com/714962 virtual/spv175/paint/float/float-text-clip.html [ Crash ] crbug.com/591099 virtual/spv175/paint/frames/frameset-with-stacking-context-and-not-stacking-context-children.html [ Failure ] crbug.com/591099 virtual/spv175/paint/frames/frameset-with-stacking-contexts.html [ Failure ] @@ -10180,62 +10172,62 @@ crbug.com/714962 virtual/spv175/paint/inline/floating-inline.html [ Crash ] crbug.com/591099 virtual/spv175/paint/inline/focus-ring-under-absolute-with-relative-continuation.html [ Failure ] crbug.com/591099 virtual/spv175/paint/inline/outline-offset.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/input/textarea-crash.html [ Crash ] +crbug.com/591099 virtual/spv175/paint/input/textarea-crash.html [ Crash Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/4774354.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/4776765.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/background/animated-gif-background.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/background/animated-png-background.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/background/animated-webp-background.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/background/background-currentColor-repaint.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/background/background-generated.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/background/animated-gif-background.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/background/animated-png-background.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/background/animated-webp-background.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/background/background-currentColor-repaint.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/background/background-generated.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/background/background-image-paint-invalidation-large-abspos-div.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/background/background-image-paint-invalidation-small-document.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/background/background-image-paint-invalidation.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/background/background-misaligned.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/background/background-resize-height.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/background/background-shorthand-with-gradient-and-height-changes.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/background/background-size-auto-with-gradient-and-height-changes.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/background/background-image-paint-invalidation-small-document.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/background/background-image-paint-invalidation.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/background/background-misaligned.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/background/background-resize-height.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/background/background-shorthand-with-gradient-and-height-changes.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/background/background-size-auto-with-gradient-and-height-changes.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/background/backgroundSizeRepaint.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/background/body-background-image.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/background/multiple-backgrounds-style-change.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/background/body-background-image.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/background/multiple-backgrounds-style-change.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/background/view-background-from-body-2.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/background/viewport-gradient-background-html-move-overflow.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/background/viewport-gradient-background-html-resize-overflow.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/background/viewport-gradient-background-html-resize.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/background/viewport-gradient-background-html-move-overflow.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/background/viewport-gradient-background-html-resize-overflow.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/background/viewport-gradient-background-html-resize.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/block-layout-inline-children-replaced.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/block-no-inflow-children.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/block-shift-repaint.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/box/border-current-color.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/box/border-image-outset-add-repaint.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/box/border-image-outset-change-repaint.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/box/border-radius-repaint-2.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/box/border-current-color.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/box/border-image-outset-add-repaint.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/box/border-image-outset-change-repaint.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/box/border-radius-repaint-2.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/box/border-radius-repaint.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/box/border-radius-without-border.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/box/border-radius-without-border.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/box/border-repaint-glitch.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/box/box-inline-resize.html [ Crash Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/box/box-shadow-add-repaint.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/box/box-shadow-change-repaint.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/box/box-shadow-add-repaint.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/box/box-shadow-change-repaint.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/box/box-shadow-dynamic.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/box/box-shadow-inset-repaint.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/box/box-sizing-border-keeping-size.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/box/box-sizing-padding-keeping-size.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/box/box-sizing.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/box/hover-pseudo-borders-whitespace.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/box/box-shadow-inset-repaint.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/box/box-sizing-border-keeping-size.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/box/box-sizing-padding-keeping-size.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/box/box-sizing.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/box/hover-pseudo-borders-whitespace.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/box/hover-pseudo-borders.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/box/invalidate-box-shadow-currentColor.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/box/margin.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/box/negative-shadow-box-expand.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/box/negative-shadow-box-shrink.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/box/padding-border-keeping-border-box-and-content-box.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/box/padding-keeping-content-size.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/box/padding-keeping-visual-size.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/box/resize-with-border.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/box/shadow-box-resize-writing-mode.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/box/shadow-box-resize.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/box/margin.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/box/negative-shadow-box-expand.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/box/negative-shadow-box-shrink.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/box/padding-border-keeping-border-box-and-content-box.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/box/padding-keeping-content-size.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/box/padding-keeping-visual-size.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/box/resize-with-border.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/box/shadow-box-resize-writing-mode.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/box/shadow-box-resize.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/bugzilla-3509.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/bugzilla-5699.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/bugzilla-6278.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/bugzilla-6388.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/bugzilla-6388.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/bugzilla-6473.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/bugzilla-7235.html [ Crash ] crbug.com/591099 virtual/spv175/paint/invalidation/clip/caret-ancestor-clip-change.html [ Failure ] @@ -10244,89 +10236,89 @@ crbug.com/591099 virtual/spv175/paint/invalidation/clip/clip-with-transform-resize.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/clip/clipped-relative.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/clip/control-clip.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/clip/css-clip-change-stacking-child.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/clip/css-clip-change-stacking-child.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/clip/intermediate-layout-position-clip.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/clip/mask-clip-change-stacking-child.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/clip/mask-clip-change-stacking-child.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/clip/outline-clip-change.html [ Failure ] crbug.com/714962 virtual/spv175/paint/invalidation/clip/repaint-subsequence-on-ancestor-clip-change-complex.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/clip/repaint-tile-clipped.html [ Crash ] crbug.com/591099 virtual/spv175/paint/invalidation/clip/replaced-clipped-positioned-not-wrong-incremental-repainting.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/clip/resize-with-border-clipped.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/clip/subtree-root-clip-2.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/clip/subtree-root-clip-3.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/clip/subtree-root-clip.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/background-attachment-local-composited.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/background-attachment-local-equivalent.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/clip/resize-with-border-clipped.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/clip/subtree-root-clip-2.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/clip/subtree-root-clip-3.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/clip/subtree-root-clip.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/background-attachment-local-composited.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/background-attachment-local-equivalent.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/compositing/become-overlay-composited-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/child-of-sub-pixel-offset-composited-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/chunk-reorder.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/clipping-should-not-repaint-composited-descendants.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/child-of-sub-pixel-offset-composited-layer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/chunk-reorder.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/clipping-should-not-repaint-composited-descendants.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/compositing/column-span-under-composited-column-child.html [ Crash ] crbug.com/591099 virtual/spv175/paint/invalidation/compositing/composited-document-element.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/composited-float-under-composited-inline-individual.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/composited-float-under-composited-inline.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/composited-float-under-composited-inline-individual.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/composited-float-under-composited-inline.html [ Failure Pass ] crbug.com/714962 virtual/spv175/paint/invalidation/compositing/composited-inline-change-text-data-keep-geometry.html [ Crash ] crbug.com/714962 virtual/spv175/paint/invalidation/compositing/composited-non-stacking-context-not-invalidation-container.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/compositing-reason-removed.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/containing-block-added-individual.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/containing-block-added.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/containing-block-removed-individual.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/containing-block-removed.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/content-into-overflow.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/dont-invalidate-root-layer-when-composited-layer-becomes-visible.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/compositing-reason-removed.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/containing-block-added-individual.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/containing-block-added.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/containing-block-removed-individual.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/containing-block-removed.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/content-into-overflow.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/dont-invalidate-root-layer-when-composited-layer-becomes-visible.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/fixed-pos-inside-composited-intermediate-layer.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/compositing/fixed-pos-with-abs-pos-child-scroll.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/fixed-scroll-in-empty-root-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/float-under-composited-inline.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/fixed-scroll-in-empty-root-layer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/float-under-composited-inline.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/compositing/iframe-clip-removed.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/compositing/iframe-inside-squashed-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/invalidate-paint-in-iframe-in-composited-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/invalidate-when-leaving-squashed-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/invalidation-for-subpixel-offset-of-squashed-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/invalidations-on-composited-layers.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/invalidations-with-large-negative-margin.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/invalidate-paint-in-iframe-in-composited-layer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/invalidate-when-leaving-squashed-layer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/invalidation-for-subpixel-offset-of-squashed-layer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/invalidations-on-composited-layers.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/invalidations-with-large-negative-margin.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/compositing/layer-repaint-rects.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/compositing/layer-repaint.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/compositing/multi-subsequence-composited.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/new-stacking-context.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/new-stacking-context.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/compositing/newly-composited-on-scroll.html [ Crash Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/compositing/opacity-between-absolute.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/compositing/opacity-between-absolute2.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/overflow-into-content.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/overflow-into-content.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/compositing/overlap-test-with-filter.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/page-scale-repaint.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/pointer-events-composited-scrolling.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/page-scale-repaint.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/pointer-events-composited-scrolling.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/compositing/remove-squashed-layer-plus-move.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/repaint-squashed-layer-in-rect.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/repaint-via-layout-offset.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/resize-repaint.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/scroll-fixed-layer-no-content.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/scroll-fixed-layer-out-of-view.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/scroll-fixed-squahed-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/scrolling-without-painting.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/should-invoke-deferred-compositing.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/repaint-squashed-layer-in-rect.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/repaint-via-layout-offset.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/resize-repaint.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/scroll-fixed-layer-no-content.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/scroll-fixed-layer-out-of-view.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/scroll-fixed-squahed-layer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/scrolling-without-painting.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/should-invoke-deferred-compositing.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/compositing/should-not-clip-composited-overflow-scrolling-layer.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/compositing/should-not-clip-composited-viewport-scrolling-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/should-not-repaint-composited-descendants-on-overflow-change.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/should-not-repaint-composited-descendants.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/should-not-repaint-composited-filter.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/should-not-repaint-composited-opacity.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/should-not-repaint-composited-transform.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/should-not-repaint-composited-z-index.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/should-not-repaint-move-backface-hidden.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/should-not-repaint-scrolling-contents-outline-change.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/squash-partial-repaint-inside-squashed-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/squashing-inside-preserve-3d-element.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/stacked-float-under-composited-inline.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/should-not-repaint-composited-descendants-on-overflow-change.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/should-not-repaint-composited-descendants.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/should-not-repaint-composited-filter.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/should-not-repaint-composited-opacity.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/should-not-repaint-composited-transform.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/should-not-repaint-composited-z-index.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/should-not-repaint-move-backface-hidden.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/should-not-repaint-scrolling-contents-outline-change.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/squash-partial-repaint-inside-squashed-layer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/squashing-inside-preserve-3d-element.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/stacked-float-under-composited-inline.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/compositing/text-color-change.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/compositing/text-match-highlight.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/tricky-element-removal-crash.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/tricky-element-removal-crash.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/compositing/updating-scrolling-container-and-content.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/updating-scrolling-container.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/compositing/updating-scrolling-content.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/crbug-371640-2.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/crbug-371640-3.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/updating-scrolling-container.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/compositing/updating-scrolling-content.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/crbug-371640-2.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/crbug-371640-3.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/crbug-371640-4.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/crbug-371640.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/create-layer-repaint.html [ Failure ] @@ -10337,33 +10329,33 @@ crbug.com/591099 virtual/spv175/paint/invalidation/css-grid-layout/grid-item-z-index-change-repaint.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/delete-into-nested-block.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/details-open-repaint.html [ Crash ] -crbug.com/591099 virtual/spv175/paint/invalidation/empty-object-move-and-resize.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-composite-1.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-composite-2.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-composite-3.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-composite-4.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-composite-5.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-composite-6.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-displacement.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-gaussianblur-xonly.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-gaussianblur-yonly.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-gaussianblur.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-lighting.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-merge.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-morphology-xonly.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-morphology-yonly.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-morphology.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-offset.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-primitive-attr-mutation.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-primitive-attr-removal.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-primitive-removed.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/filter-invalidation-after-display.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/filter-invalidation-positioned-child.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/filter-invalidation-with-composited-container-change.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/filter-on-html-element-with-fixed-position-child.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/filter-repaint-accelerated-child-with-filter-child.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/filter-repaint-accelerated-on-accelerated-filter.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/filters/filter-repaint-on-accelerated-layer.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/empty-object-move-and-resize.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-composite-1.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-composite-2.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-composite-3.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-composite-4.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-composite-5.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-composite-6.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-displacement.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-gaussianblur-xonly.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-gaussianblur-yonly.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-gaussianblur.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-lighting.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-merge.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-morphology-xonly.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-morphology-yonly.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-morphology.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-offset.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-primitive-attr-mutation.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-primitive-attr-removal.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/effect-reference-repaint-primitive-removed.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/filter-invalidation-after-display.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/filter-invalidation-positioned-child.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/filter-invalidation-with-composited-container-change.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/filter-on-html-element-with-fixed-position-child.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/filter-repaint-accelerated-child-with-filter-child.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/filter-repaint-accelerated-on-accelerated-filter.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/filters/filter-repaint-on-accelerated-layer.html [ Failure Pass ] crbug.com/714962 virtual/spv175/paint/invalidation/first-line-inline-child.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/flexbox/align-content-change-keeping-geometry.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/flexbox/align-content-change.html [ Failure ] @@ -10388,10 +10380,10 @@ crbug.com/591099 virtual/spv175/paint/invalidation/flexbox/repaint-rtl-column.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/flexbox/repaint.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/flexbox/scrollbars-changed.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/float-in-new-block-with-layout-delta.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/float-in-new-block-with-layout-delta.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/float-move-during-layout.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/float-new-in-block.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/forms/button-checkbox-click-method-repaint.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/float-new-in-block.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/forms/button-checkbox-click-method-repaint.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/forms/button-reset-focus-by-mouse-then-keydown.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/forms/checkbox-focus-by-mouse-then-keydown.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/forms/radio-focus-by-mouse-then-keydown.html [ Failure ] @@ -10404,23 +10396,23 @@ crbug.com/591099 virtual/spv175/paint/invalidation/gradients-em-stops-repaint.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/iframe-display-block-to-display-none.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/iframe-display-none-to-display-block.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/iframe-rounding.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/image/animated-gif-transformed-offscreen.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/iframe-rounding.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/image/animated-gif-transformed-offscreen.html [ Failure Pass ] crbug.com/714962 virtual/spv175/paint/invalidation/image/percent-size-image-resize-container.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/in-scaled-iframe.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/in-scaled-iframe.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/inline-block-resize.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/inline-color-change.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/inline-reflow.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/insert-frame.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/invalidate-descendants-when-receiving-paint-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/invalidate-invisible-element.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/invalidate-descendants-when-receiving-paint-layer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/invalidate-invisible-element.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/invalidation-after-opacity-change-subtree.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/invalidation-on-foreground-graphics-layer.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/invalidation-on-foreground-graphics-layer.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/invalidation-with-zero-size-object.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/invisible-objects.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/layer-full-repaint.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/layer-hide-when-needs-layout.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/layer-visibility.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/layer-full-repaint.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/layer-hide-when-needs-layout.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/layer-visibility.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/line-flow-with-floats-1.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/line-flow-with-floats-10.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/line-flow-with-floats-2.html [ Failure ] @@ -10436,14 +10428,14 @@ crbug.com/591099 virtual/spv175/paint/invalidation/list-marker.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/make-children-non-inline.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/mix-blend-mode-separate-stacking-context.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/multicol/column-float-under-stacked-inline.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/multicol/column-float-under-stacked-inline.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/multicol/column-rule-change.html [ Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/multicol/column-rules-fixed-height.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/multicol/multicol-as-paint-container.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/multicol/multicol-nested.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/multicol/multicol-relpos-with-abspos.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/multicol/multicol-repaint.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/multicol/multicol-resize-with-rule.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/multicol/multicol-resize-with-rule.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/multicol/multicol-rule-actual-columns-change.html [ Crash ] crbug.com/591099 virtual/spv175/paint/invalidation/multicol/multicol-with-abspos-in-relpos.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/multicol/multicol-with-abspos.html [ Failure ] @@ -10452,13 +10444,14 @@ crbug.com/591099 virtual/spv175/paint/invalidation/multicol/multicol-with-relpos.html [ Crash Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/multicol/multicol-with-text.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/non-text-link-invalidation-optimization.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/outline/border-outline-0.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/outline/border-radius-with-outline.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/offset-change-wrong-invalidation-with-float.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/outline/border-outline-0.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/outline/border-radius-with-outline.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/outline/continuation-after-outline.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/outline/focus-continuations.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/outline/focus-enable-continuations.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/outline/focus-layers.html [ Crash Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/outline/focus-ring-on-child-move.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/outline/focus-ring-on-child-move.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/outline/focus-ring-on-continuation-move.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/outline/focus-ring-on-inline-continuation-move.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/outline/focus-ring.html [ Failure ] @@ -10468,32 +10461,32 @@ crbug.com/591099 virtual/spv175/paint/invalidation/outline/layer-child-outline.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/outline/layer-outline-horizontal.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/outline/layer-outline.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-add-repaint.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-become-affected-by-descendant.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-become-not-affected-by-descendant.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-add-repaint.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-become-affected-by-descendant.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-become-not-affected-by-descendant.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-change-continuations.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-change-invalidation.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-change-offset.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-change-repaint.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-change-offset.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-change-repaint.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-change-vertical-rl.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-child-repaint.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-child-repaint.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-containing-image-in-non-standard-mode.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-continuations.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-current-color.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-current-color.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-inset.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-not-affected-by-descendant.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-not-affected-by-descendant.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-repaint-glitch.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/outline/outline-shrinking.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/overflow/align-items-overflow-change.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/overflow/align-self-overflow-change.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/overflow/clipped-overflow-visible-subtree.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/overflow/composited-overflow-with-borderbox-background.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/overflow/composited-overflow-with-local-background.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/overflow/composited-overflow-with-negative-offset-outline.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/overflow/composited-vertical-rl-overflow.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/overflow/content-into-overflow.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/overflow/erase-overflow.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/overflow/fixed-position-transparency-with-overflow.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/overflow/clipped-overflow-visible-subtree.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/overflow/composited-overflow-with-borderbox-background.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/overflow/composited-overflow-with-local-background.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/overflow/composited-overflow-with-negative-offset-outline.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/overflow/composited-vertical-rl-overflow.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/overflow/content-into-overflow.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/overflow/erase-overflow.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/overflow/fixed-position-transparency-with-overflow.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/overflow/flexible-box-overflow-horizontal.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/overflow/flexible-box-overflow.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/overflow/float-overflow-right.html [ Crash Failure ] @@ -10508,140 +10501,143 @@ crbug.com/591099 virtual/spv175/paint/invalidation/overflow/justify-self-overflow-change.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/overflow/line-overflow.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/overflow/negative-text-indent-with-overflow-hidden.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/overflow/opacity-change-on-overflow-float.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/overflow/overflow-changed-on-child-of-composited-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/overflow/overflow-clip-subtree-layout.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/overflow/opacity-change-on-overflow-float.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/overflow/overflow-changed-on-child-of-composited-layer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/overflow/overflow-clip-subtree-layout.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/overflow/overflow-hidden-to-visible.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/overflow/overflow-hide.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/overflow/overflow-into-content.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/overflow/overflow-hide.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/overflow/overflow-into-content.html [ Failure Pass ] crbug.com/714962 virtual/spv175/paint/invalidation/overflow/overflow-outline-repaint.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/overflow/overflow-show.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/overflow/rel-positioned-inline-with-overflow.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/overflow/overflow-show.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/overflow/rel-positioned-inline-with-overflow.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/overflow/repaint-resized-overflow.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/overflow/resize-child-within-overflow.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/overflow/trailing-floats-root-line-box-overflow.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/overflow/vertical-overflow-child.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/overflow/resize-child-within-overflow.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/overflow/trailing-floats-root-line-box-overflow.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/overflow/vertical-overflow-child.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/overflow/vertical-overflow-parent.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/overflow/vertical-overflow-same.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/overflow/vertical-rl-overflow.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/overhanging-float-detach-repaint.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/paint-caret-in-div-with-negative-indent.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/paint-invalidation-with-opacity.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/overflow/vertical-rl-overflow.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/overhanging-float-detach-repaint.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/paint-caret-in-div-with-negative-indent.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/paint-invalidation-with-opacity.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/paint-invalidation-with-reparent-across-frame-boundaries.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/position/absolute-display-block-to-none.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/position/absolute-display-block-to-none.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/position/absolute-layer-specified-left-or-right-auto-width-moved-vertically.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/position/absolute-margin-change-repaint.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/position/absolute-position-change-containing-block.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/position/absolute-position-changed.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/position/absolute-position-moved.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/position/absolute-position-changed.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/position/absolute-position-moved.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/position/abspos-shift-image-incorrect-repaint.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/position/align-content-position-change-grid.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/position/block-layout-inline-children-float-positioned.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/position/containing-block-position-change.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/position/fixed-element-repaint-after-compositing-update.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/position/fixed-margin-change-repaint.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/position/fixed-element-repaint-after-compositing-update.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/position/fixed-margin-change-repaint.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/position/fixed-position-layer-moved.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/position/fixed-scale.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/position/fixed-scale.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/position/fixed-to-relative-position-with-absolute-child.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/position/fixed-tranformed.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/position/fixed.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/position/fixed-tranformed.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/position/fixed.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/position/inline-relative-positioned.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/position/intermediate-layout-position.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/position/invalidate-paint-for-fixed-pos-inside-iframe.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/position/invalidate-paint-for-fixed-pos-inside-iframe.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/position/justify-content-position-change-grid.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/position/justify-content-position-change.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/position/layout-state-only-positioned.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/position/layout-state-only-positioned.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/position/layout-state-relative.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/position/layoutstate-invalid-invalidation-inline-relative-positioned.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/position/positioned-document-element.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/position/positioned-great-grandparent-change-location.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/position/positioned-list-offset-change-repaint.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/position/relative-inline-positioned-movement-repaint.html [ Crash Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/position/relative-margin-change-repaint.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/position/relative-positioned-movement-repaint.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/position/relative-margin-change-repaint.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/position/relative-positioned-movement-repaint.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/position/relayout-fixed-position-after-scale.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/position/shift-relative-positioned-container-with-image-addition.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/position/shift-relative-positioned-container-with-image-removal.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/position/static-to-positioned.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/position/text-in-relative-positioned-inline.html [ Crash Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/position/transform-absolute-child.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/position/transform-absolute-child.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/position/transform-absolute-in-positioned-container.html [ Crash Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/position/transform-relative-position.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/position/transform-relative-position.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/push-block-with-first-line.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/quotes.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/raster-under-invalidation-checking.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/reflection/reflection-invalidation-after-display.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/reflection/reflection-invalidation-positioned-child.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/raster-under-invalidation-checking.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/reflection/reflection-invalidation-after-display.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/reflection/reflection-invalidation-positioned-child.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/reflection/reflection-redraw.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/reflection/scroll-absolute-layer-with-reflection.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/reflection/scroll-fixed-layer-with-reflection.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/reflection/scroll-fixed-reflected-layer.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/reflection/scroll-absolute-layer-with-reflection.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/reflection/scroll-fixed-layer-with-reflection.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/reflection/scroll-fixed-reflected-layer.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/remove-block-after-layout.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/remove-inline-after-layout.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/remove-inline-layer-after-layout.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/renderer-destruction-by-invalidateSelection-crash.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/repaint-across-writing-mode-boundary.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/repaint-descandant-on-ancestor-layer-move.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/repaint-in-iframe.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/repaint-on-style-change.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/repaint-in-iframe.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/repaint-on-style-change.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/repaint-overlay/layers-overlay.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/repaint-overlay/layers.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/repaint-subrect-grid.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/requestAnimation-translation-leave-traces.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/repaint-overlay/layers.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/repaint-subrect-grid.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/requestAnimation-translation-leave-traces.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/resize-iframe-text.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/ruby-flipped-blocks.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/scroll/caret-with-composited-scroll.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/composited-add-resizer.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/composited-iframe-scroll-repaint.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/destroy-composited-scrollbar.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/destroy-overlay-scrollbar.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/destroy-scrollbar.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/fixed-after-scroll.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/fixed-and-absolute-position-scrolled.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/fixed-child-move-after-scroll.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/fixed-child-of-fixed-move-after-scroll.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/composited-add-resizer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/composited-iframe-scroll-repaint.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/destroy-composited-scrollbar.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/destroy-overlay-scrollbar.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/destroy-scrollbar.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/fixed-after-scroll.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/fixed-and-absolute-position-scrolled.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/fixed-child-move-after-scroll.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/fixed-child-of-fixed-move-after-scroll.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/scroll/fixed-child-of-transformed-move-after-scroll.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/fixed-child-of-transformed-scrolled.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/fixed-descendant-of-transformed-scrolled.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/fixed-move-after-scroll.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/fixed-scroll-simple.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/fixed-child-of-transformed-scrolled.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/fixed-descendant-of-transformed-scrolled.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/fixed-move-after-scroll.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/fixed-scroll-simple.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/scroll/fixed-under-composited-absolute-scrolled.html [ Crash ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/fixed-under-composited-fixed-scrolled.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/fixed-under-composited-fixed-scrolled.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/scroll/fixed-with-border-under-composited-absolute-scrolled.html [ Crash ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/flipped-blocks-writing-mode-scroll.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/flipped-blocks-writing-mode-scroll.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/scroll/iframe-scroll-repaint.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/scroll/inline-style-change-in-scrolled-view.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/scroll/invalidate-after-composited-scroll-of-window.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/invalidate-after-composited-scroll.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/invalidate-after-composited-scroll.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/scroll/layout-state-scrolloffset.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/scroll/layout-state-scrolloffset2.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/scroll/layout-state-scrolloffset3.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/scroll/line-in-scrolled-clipped-block.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/nested-fixed-iframe-scrolled.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/nested-fixed-iframe-scrolled.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/scroll/outline-change-in-scrollers.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/outline-change-scrollable.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/overflow-hidden-in-overflow-hidden-scrolled.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/overflow-hidden-yet-scrolled-with-custom-scrollbar.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/overflow-hidden-yet-scrolled.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/overflow-move-after-scroll.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/overflow-scroll-after-move.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/outline-change-scrollable.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/overflow-auto-in-overflow-auto-scrolled.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/overflow-hidden-in-overflow-hidden-scrolled.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/overflow-hidden-yet-scrolled-with-custom-scrollbar.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/overflow-hidden-yet-scrolled.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/overflow-move-after-scroll.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/overflow-scroll-after-move.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/scroll/overflow-scroll-body-appear.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/scroll/overflow-scroll-delete.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/overflow-scroll-local-background-text-color-change.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/repaint-composited-child-in-scrolled-container.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/overflow-scroll-local-background-text-color-change.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/repaint-composited-child-in-scrolled-container.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/repaint-during-scroll-with-zoom.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/scroll/repaint-during-scroll.html [ Timeout ] crbug.com/591099 virtual/spv175/paint/invalidation/scroll/resize-scrollable-div.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/scroll-fixed-layer-with-no-visible-content.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/scroll-fixed-layer-with-transformed-parent-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/scroll-in-clipped-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/scroll-in-fixed-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/scroll-in-transformed-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/scroll-with-transformed-parent-layer.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/scroll/scrollbar-ancestor-clip-change.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/resize-scrollable-iframe.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/scroll-descendant-with-cached-cliprects.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/scroll-fixed-layer-with-no-visible-content.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/scroll-fixed-layer-with-transformed-parent-layer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/scroll-in-clipped-layer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/scroll-in-fixed-layer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/scroll-in-transformed-layer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/scroll-stacking-context-backface-visiblity-leaves-traces.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/scroll-with-transformed-parent-layer.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/scroll/scrollbar-ancestor-clip-change.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/scroll/scrollbar-invalidation-on-resize-with-border.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/scroll/scrollbar-invalidation-on-resize.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/scroll/scrolled-iframe-scrollbar-change.html [ Failure ] @@ -10672,11 +10668,11 @@ crbug.com/591099 virtual/spv175/paint/invalidation/svg/add-background-property-on-root.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/svg/add-outline-property-on-root.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/svg/animated-path-inside-transformed-html.xhtml [ Failure Pass ] -crbug.com/591099 virtual/spv175/paint/invalidation/svg/animated-svg-as-image-transformed-offscreen.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/svg/animated-svg-as-image-transformed-offscreen.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/svg/deep-nested-embedded-svg-size-changes-no-layout-triggers-1.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/svg/deep-nested-embedded-svg-size-changes-no-layout-triggers-2.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/svg/embedded-svg-size-changes-no-layout-triggers.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/svg/foreign-object-repaint.svg [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/svg/foreign-object-repaint.svg [ Failure Pass ] crbug.com/714962 virtual/spv175/paint/invalidation/svg/hit-test-with-br.xhtml [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/svg/nested-embedded-svg-size-changes-no-layout-triggers-1.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/svg/nested-embedded-svg-size-changes-no-layout-triggers-2.html [ Failure ] @@ -10693,19 +10689,19 @@ crbug.com/591099 virtual/spv175/paint/invalidation/svg/relative-sized-use-without-attributes-on-symbol.xhtml [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/svg/remove-background-property-on-root.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/svg/remove-outline-property-on-root.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/svg/repaint-moving-svg-and-div.xhtml [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/svg/repaint-svg-after-style-change.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/svg/repaint-moving-svg-and-div.xhtml [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/svg/repaint-svg-after-style-change.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/svg/resize-svg-invalidate-children-2.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/svg/resize-svg-invalidate-children.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/svg/scroll-hit-test.xhtml [ Crash Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/svg/scrolling-embedded-svg-file-image-repaint-problem.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/svg/svg-background-partial-redraw.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/svg/svg-image-change-content-size.xhtml [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/svg/svg-layout-root-style-attr-update.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/svg/svg-layout-root-style-attr-update.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/svg/text-rescale.html [ Failure ] crbug.com/714962 virtual/spv175/paint/invalidation/svg/text-xy-updates-SVGList.xhtml [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/svg/transform-focus-ring-repaint.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/svg/transform-foreign-object.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/svg/transform-focus-ring-repaint.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/svg/transform-foreign-object.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/svg/use-instanceRoot-event-bubbling.xhtml [ Crash Pass Timeout ] crbug.com/591099 virtual/spv175/paint/invalidation/svg/use-setAttribute-crash.svg [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/table/add-table-overpaint.html [ Failure ] @@ -10745,7 +10741,7 @@ crbug.com/591099 virtual/spv175/paint/invalidation/table/fixed-table-cell.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/table/fixed-table-overflow-zindex.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/table/fixed-table-overflow.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/table/input-overflow-in-table.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/table/input-overflow-in-table.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/table/invalidate-cell-in-row-with-offset.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/table/repaint-table-row-in-composited-document.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/table/resize-table-repaint-percent-size-cell.html [ Failure ] @@ -10757,7 +10753,7 @@ crbug.com/714962 virtual/spv175/paint/invalidation/table/table-cell-become-visible-using-row-background.html [ Crash ] crbug.com/591099 virtual/spv175/paint/invalidation/table/table-cell-collapsed-border.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/table/table-cell-move.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/table/table-cell-overflow.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/table/table-cell-overflow.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/table/table-cell-vertical-overflow.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/table/table-collapsed-border.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/table/table-extra-bottom-grow.html [ Failure ] @@ -10782,17 +10778,17 @@ crbug.com/591099 virtual/spv175/paint/invalidation/text-shadow-horizontal.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/text-shadow.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/transform/change-transform.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/transform/invalidation-with-scale-transform.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/transform/resize-skewed.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/transform/rotated-subpixel.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/transform/subpixel-offset-scaled-transform.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/transform/subtree-layoutstate-transform.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/transform/transform-disable-layoutstate.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/transform/invalidation-with-scale-transform.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/transform/resize-skewed.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/transform/rotated-subpixel.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/transform/subpixel-offset-scaled-transform.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/transform/subtree-layoutstate-transform.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/transform/transform-disable-layoutstate.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/transform/transform-inline-layered-child.html [ Crash Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/transform/transform-layout-repaint.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/transform/transform-repaint-descendants.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/transform/transform-rotate-and-remove.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/transform/transform-translate.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/transform/transform-repaint-descendants.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/transform/transform-rotate-and-remove.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/transform/transform-translate.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/vertical-align-length1.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/vertical-align-length2.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/vertical-align1.html [ Failure ] @@ -10801,46 +10797,45 @@ crbug.com/591099 virtual/spv175/paint/invalidation/video-mute-repaint.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/video-unmute-repaint.html [ Failure ] crbug.com/591099 virtual/spv175/paint/invalidation/window-resize/window-resize-centered-inline-under-fixed-pos.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/window-resize/window-resize-percent-html.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/window-resize/window-resize-percent-width-height.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/window-resize/window-resize-positioned-bottom.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/window-resize/window-resize-positioned-percent-top.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/window-resize/window-resize-percent-html.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/window-resize/window-resize-percent-width-height.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/window-resize/window-resize-positioned-bottom.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/invalidation/window-resize/window-resize-positioned-percent-top.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/invalidation/window-resize/window-resize-vertical-writing-mode.html [ Crash Failure ] -crbug.com/591099 virtual/spv175/paint/invalidation/window-resize/window-resize-viewport-percent.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/invalidation/window-resize/window-resize-viewport-percent.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/markers/active-suggestion-marker-basic.html [ Failure ] crbug.com/591099 virtual/spv175/paint/markers/active-suggestion-marker-split.html [ Failure ] crbug.com/591099 virtual/spv175/paint/markers/composition-marker-basic.html [ Failure ] crbug.com/591099 virtual/spv175/paint/markers/composition-marker-split.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/markers/document-markers-zoom-125.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/markers/document-markers-zoom-150.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/markers/document-markers-zoom-175.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/markers/document-markers-zoom-200.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/markers/document-markers-zoom-250.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/markers/document-markers.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/markers/document-markers-zoom-125.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/markers/document-markers-zoom-150.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/markers/document-markers-zoom-175.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/markers/document-markers-zoom-200.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/markers/document-markers-zoom-250.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/markers/document-markers.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/markers/ellipsis-ltr-text-in-ltr-flow-with-markers.html [ Failure ] crbug.com/591099 virtual/spv175/paint/markers/ellipsis-ltr-text-in-rtl-flow-with-markers.html [ Failure ] crbug.com/591099 virtual/spv175/paint/markers/ellipsis-mixed-text-in-ltr-flow-with-markers.html [ Failure ] crbug.com/591099 virtual/spv175/paint/markers/ellipsis-mixed-text-in-rtl-flow-with-markers.html [ Failure ] crbug.com/591099 virtual/spv175/paint/markers/ellipsis-rtl-text-in-ltr-flow-with-markers.html [ Failure ] crbug.com/591099 virtual/spv175/paint/markers/ellipsis-rtl-text-in-rtl-flow-with-markers.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/markers/grammar-markers-hidpi.html [ Crash Failure ] -crbug.com/591099 virtual/spv175/paint/markers/grammar-markers.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/markers/grammar-markers-hidpi.html [ Crash Failure Pass ] +crbug.com/591099 virtual/spv175/paint/markers/grammar-markers.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/markers/inline-spelling-markers-hidpi-composited.html [ Failure ] crbug.com/591099 virtual/spv175/paint/markers/inline-spelling-markers-hidpi.html [ Crash Failure ] crbug.com/591099 virtual/spv175/paint/markers/inline_spelling_markers.html [ Failure ] crbug.com/591099 virtual/spv175/paint/markers/marker-early-break-bug.html [ Failure ] crbug.com/591099 virtual/spv175/paint/markers/suggestion-marker-basic.html [ Failure ] crbug.com/591099 virtual/spv175/paint/markers/suggestion-marker-split.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/masks/fieldset-mask.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/masks/fieldset-mask.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/overflow/composited-rounded-clip-floating-element.html [ Failure ] crbug.com/591099 virtual/spv175/paint/overflow/fixed-background-scroll-window.html [ Failure ] crbug.com/591099 virtual/spv175/paint/overflow/non-composited-fixed-position-descendant.html [ Failure ] crbug.com/591099 virtual/spv175/paint/pagination/composited-paginated-inline.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/printing/print-box-shadow.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/printing/print-box-shadow.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/printing/print-text-shadow.html [ Failure ] crbug.com/591099 virtual/spv175/paint/roundedrects/circle-with-shadow.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/roundedrects/input-with-rounded-rect-and-shadow.html [ Failure ] -crbug.com/714962 virtual/spv175/paint/selection/text-selection-counter.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/roundedrects/input-with-rounded-rect-and-shadow.html [ Failure Pass ] crbug.com/714962 virtual/spv175/paint/selection/text-selection-drag.html [ Failure ] crbug.com/591099 virtual/spv175/paint/selection/text-selection-inline-block-rtl.html [ Crash Failure ] crbug.com/591099 virtual/spv175/paint/selection/text-selection-inline-block.html [ Crash Failure ] @@ -10857,15 +10852,15 @@ crbug.com/591099 virtual/spv175/paint/selection/text-selection-newline-vertical-rl.html [ Failure ] crbug.com/591099 virtual/spv175/paint/selection/text-selection-newline.html [ Failure ] crbug.com/714962 virtual/spv175/paint/selection/text-selection-update-style.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/selection/text-selection-with-composition.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/subpixel/transform-inside-clip.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/selection/text-selection-with-composition.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/subpixel/transform-inside-clip.html [ Failure Pass ] crbug.com/591099 virtual/spv175/paint/tables/collapsed-border-corner-conflict.html [ Failure ] crbug.com/591099 virtual/spv175/paint/tables/composited-collapsed-table-borders.html [ Failure ] crbug.com/591099 virtual/spv175/paint/text/selection-no-clip-text.html [ Failure ] crbug.com/714962 virtual/spv175/paint/text/text-match-highlights-big-line-height.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/theme/adjust-progress-bar-size.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/transforms/percentage-transform-fractional-box-size.html [ Failure ] -crbug.com/591099 virtual/spv175/paint/transparency/compositing-alpha-fold-crash.html [ Failure ] +crbug.com/591099 virtual/spv175/paint/theme/adjust-progress-bar-size.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/transforms/percentage-transform-fractional-box-size.html [ Failure Pass ] +crbug.com/591099 virtual/spv175/paint/transparency/compositing-alpha-fold-crash.html [ Failure Pass ] crbug.com/591099 virtual/spv2/compositing/framesets/composited-frame-alignment.html [ Failure ] crbug.com/591099 virtual/spv2/compositing/geometry/outline-change.html [ Failure ] crbug.com/591099 virtual/spv2/paint/invalidation/box/margin.html [ Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process b/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process index 3fb15626..6dc2bad 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process +++ b/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process
@@ -107,8 +107,6 @@ # http/ flaky tests w/ --site-per-process crbug.com/678481 http/tests/devtools/appcache/appcache-iframe-manifests.js [ Timeout Pass ] crbug.com/678482 http/tests/devtools/debugger/fetch-breakpoints.js [ Timeout Pass ] -crbug.com/678484 http/tests/devtools/startup/reattach-after-editing-styles.html [ Timeout Pass ] -crbug.com/678485 http/tests/devtools/startup/shadow-dom-rules-restart.html [ Timeout ] crbug.com/678491 http/tests/misc/webtiming-no-origin.html [ Crash Pass ] # Slow tests. These are listed in SlowTests listed here also because
diff --git a/third_party/WebKit/LayoutTests/SlowTests b/third_party/WebKit/LayoutTests/SlowTests index 88ca6beb..082f069 100644 --- a/third_party/WebKit/LayoutTests/SlowTests +++ b/third_party/WebKit/LayoutTests/SlowTests
@@ -108,7 +108,7 @@ crbug.com/667560 http/tests/devtools/startup/console/console-format-startup.js [ Slow ] crbug.com/679833 http/tests/devtools/network/network-datareceived.js [ Slow ] webkit.org/b/90488 [ Release ] http/tests/devtools/compiler-source-mapping-debug.js [ Slow ] -crbug.com/243492 http/tests/devtools/startup/injected-script-discard.html [ Slow ] +crbug.com/243492 inspector-protocol/injected-script-discard.js [ Slow ] crbug.com/327078 http/tests/devtools/network/long-script-content.js [ Slow ] crbug.com/420008 [ Release ] http/tests/devtools/editor/text-editor-word-jumps.js [ Slow ] crbug.com/420008 [ Release ] http/tests/devtools/console-xhr-logging.js [ Slow ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index f9c4d4e0..b39ef7d 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1947,7 +1947,7 @@ crbug.com/655458 crbug.com/721814 external/wpt/mediacapture-image/idlharness.html [ Skip ] crbug.com/626703 external/wpt/web-nfc/idlharness.https.html [ Skip ] -crbug.com/723741 virtual/threaded/http/tests/devtools/tracing/idle-callback.html [ Failure Pass Timeout ] +crbug.com/723741 virtual/threaded/http/tests/devtools/tracing/idle-callback.js [ Failure Pass Timeout ] crbug.com/723826 http/tests/security/w3c/cross-origin-objects.html [ Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/notifications/characteristic-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/notifications/characteristic-is-removed.html index 6e6eea1..f1e08e4 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/notifications/characteristic-is-removed.html +++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/notifications/characteristic-is-removed.html
@@ -6,20 +6,16 @@ <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> <script> 'use strict'; -bluetooth_test(() => { - return setBluetoothFakeAdapter('HeartRateAdapter') - .then(() => requestDeviceWithTrustedClick({ - filters: [{services: ['heart_rate']}]})) - .then(device => device.gatt.connect()) - .then(gattService => gattService.getPrimaryService('heart_rate')) - .then(service => service.getCharacteristic('heart_rate_measurement')) - .then(characteristic => { - return setBluetoothFakeAdapter('MissingCharacteristicHeartRateAdapter') - .then(() => assert_promise_rejects_with_message( - characteristic.startNotifications(), - new DOMException('GATT Characteristic no longer exists.', - 'InvalidStateError'), - 'Characteristic got removed.')); - }); -}, 'Characteristic is removed. Reject with InvalidStateError.'); +const test_desc = 'Characteristic is removed. Reject with InvalidStateError.'; +let characteristic, fake_characteristic; + +bluetooth_test(() => getMeasurementIntervalCharacteristic() + .then(_ => ({characteristic, fake_characteristic} = _)) + .then(() => fake_characteristic.remove()) + .then(() => assert_promise_rejects_with_message( + characteristic.startNotifications(), + new DOMException('GATT Characteristic no longer exists.', + 'InvalidStateError'), + 'Characteristic got removed.')), + test_desc); </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/characteristic-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/characteristic-is-removed.html index 279fd5a3..36e29d2 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/characteristic-is-removed.html +++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/readValue/characteristic-is-removed.html
@@ -6,22 +6,17 @@ <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> <script> 'use strict'; -bluetooth_test(() => { - return setBluetoothFakeAdapter('HeartRateAdapter') - .then(() => requestDeviceWithTrustedClick({ - filters: [{services: ['heart_rate']}], - optionalServices: ['generic_access']})) - .then(device => device.gatt.connect()) - .then(gattServer => gattServer.getPrimaryService('generic_access')) - .then(service => service.getCharacteristic('gap.device_name')) - .then(characteristic => { - return setBluetoothFakeAdapter('MissingCharacteristicHeartRateAdapter') - .then(() => assert_promise_rejects_with_message( - characteristic.readValue(), - new DOMException( - 'GATT Characteristic no longer exists.', - 'InvalidStateError'), - 'Characteristic got removed.')); - }); -}, 'Characteristic gets removed. Reject with InvalidStateError.'); +const test_desc = 'Characteristic gets removed. Reject with InvalidStateError.'; +let characteristic, fake_characteristic; + +bluetooth_test(() => getMeasurementIntervalCharacteristic() + .then(_ => ({characteristic, fake_characteristic} = _)) + .then(() => fake_characteristic.remove()) + .then(() => assert_promise_rejects_with_message( + characteristic.readValue(), + new DOMException( + 'GATT Characteristic no longer exists.', + 'InvalidStateError'), + 'Characteristic got removed.')), + test_desc); </script>
diff --git a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/characteristic-is-removed.html b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/characteristic-is-removed.html index e416ce5..d4f7bd8 100644 --- a/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/characteristic-is-removed.html +++ b/third_party/WebKit/LayoutTests/bluetooth/characteristic/writeValue/characteristic-is-removed.html
@@ -6,21 +6,16 @@ <script src="../../../resources/bluetooth/bluetooth-helpers.js"></script> <script> 'use strict'; -bluetooth_test(() => { - return setBluetoothFakeAdapter('HeartRateAdapter') - .then(() => requestDeviceWithTrustedClick({ - filters: [{services: ['heart_rate']}], - optionalServices: ['generic_access']})) - .then(device => device.gatt.connect()) - .then(gattServer => gattServer.getPrimaryService('generic_access')) - .then(service => service.getCharacteristic('gap.device_name')) - .then(characteristic => { - return setBluetoothFakeAdapter('MissingCharacteristicHeartRateAdapter') - .then(() => assert_promise_rejects_with_message( - characteristic.writeValue(new ArrayBuffer(1 /* length */)), - new DOMException( - 'GATT Characteristic no longer exists.', 'InvalidStateError'), - 'Characteristic got removed.')); - }); -}, 'Characteristic gets removed. Reject with InvalidStateError.'); +const test_desc = 'Characteristic gets removed. Reject with InvalidStateError.'; +let characteristic, fake_characteristic; + +bluetooth_test(() => getMeasurementIntervalCharacteristic() + .then(_ => ({characteristic, fake_characteristic} = _)) + .then(() => fake_characteristic.remove()) + .then(() => assert_promise_rejects_with_message( + characteristic.writeValue(new ArrayBuffer(1 /* length */)), + new DOMException( + 'GATT Characteristic no longer exists.', 'InvalidStateError'), + 'Characteristic got removed.')), + test_desc); </script>
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json index 9312080..f12e353 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -33533,6 +33533,30 @@ {} ] ], + "css/css-display/display-contents-button.html": [ + [ + "/css/css-display/display-contents-button.html", + [ + [ + "/css/css-display/display-contents-pass-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-display/display-contents-details.html": [ + [ + "/css/css-display/display-contents-details.html", + [ + [ + "/css/css-display/display-contents-pass-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-display/display-contents-dynamic-before-after-001.html": [ [ "/css/css-display/display-contents-dynamic-before-after-001.html", @@ -33773,6 +33797,18 @@ {} ] ], + "css/css-display/display-contents-fieldset.html": [ + [ + "/css/css-display/display-contents-fieldset.html", + [ + [ + "/css/css-display/display-contents-pass-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-display/display-contents-first-letter-001.html": [ [ "/css/css-display/display-contents-first-letter-001.html", @@ -93874,6 +93910,11 @@ {} ] ], + "cookie-store/serviceworker_cookiestore_basic.js": [ + [ + {} + ] + ], "cookies/OWNERS": [ [ {} @@ -125594,6 +125635,11 @@ {} ] ], + "encoding/big5-encoder-expected.txt": [ + [ + {} + ] + ], "encoding/eof-shift_jis-ref.html": [ [ {} @@ -125614,6 +125660,11 @@ {} ] ], + "encoding/gbk-encoder-expected.txt": [ + [ + {} + ] + ], "encoding/iso-2022-jp-decoder-expected.txt": [ [ {} @@ -136704,6 +136755,16 @@ {} ] ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/class-bad.vtt": [ + [ + {} + ] + ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/class.vtt": [ + [ + {} + ] + ], "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id-error.vtt": [ [ {} @@ -136759,6 +136820,16 @@ {} ] ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/entities-wrong.vtt": [ + [ + {} + ] + ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/entities.vtt": [ + [ + {} + ] + ], "html/semantics/embedded-content/media-elements/track/track-element/resources/iso2022jp3.vtt": [ [ {} @@ -136774,6 +136845,16 @@ {} ] ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/markup-bad.vtt": [ + [ + {} + ] + ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/markup.vtt": [ + [ + {} + ] + ], "html/semantics/embedded-content/media-elements/track/track-element/resources/metadata-area.vtt": [ [ {} @@ -136819,6 +136900,16 @@ {} ] ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp-bad.vtt": [ + [ + {} + ] + ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp.vtt": [ + [ + {} + ] + ], "html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour-error.vtt": [ [ {} @@ -136864,6 +136955,21 @@ {} ] ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/valign-bad.vtt": [ + [ + {} + ] + ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/valign-ltr.vtt": [ + [ + {} + ] + ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/valign.vtt": [ + [ + {} + ] + ], "html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-file.vtt": [ [ {} @@ -165509,12 +165615,6 @@ {} ] ], - "cookie-store/document_get_set.tentative.html": [ - [ - "/cookie-store/document_get_set.tentative.html", - {} - ] - ], "cookie-store/document_has.tentative.html": [ [ "/cookie-store/document_has.tentative.html", @@ -165553,6 +165653,12 @@ } ] ], + "cookie-store/get_set.tentative.window.js": [ + [ + "/cookie-store/get_set.tentative.window.html", + {} + ] + ], "cookie-store/get_set_get_all.tentative.html": [ [ "/cookie-store/get_set_get_all.tentative.html", @@ -165793,6 +165899,12 @@ } ] ], + "cookie-store/serviceworker_cookiestore_basic.tentative.https.html": [ + [ + "/cookie-store/serviceworker_cookiestore_basic.tentative.https.html", + {} + ] + ], "cookies/meta-blocked.html": [ [ "/cookies/meta-blocked.html", @@ -182323,6 +182435,12 @@ {} ] ], + "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-class-markup.html": [ + [ + "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-class-markup.html", + {} + ] + ], "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-identifiers.html": [ [ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-identifiers.html", @@ -182347,6 +182465,12 @@ {} ] ], + "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-entities.html": [ + [ + "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-entities.html", + {} + ] + ], "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-header-comment.html": [ [ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-header-comment.html", @@ -182365,6 +182489,12 @@ {} ] ], + "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-markup.html": [ + [ + "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-markup.html", + {} + ] + ], "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-newlines.html": [ [ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-newlines.html", @@ -182389,6 +182519,12 @@ {} ] ], + "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timestamp.html": [ + [ + "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timestamp.html", + {} + ] + ], "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-hour.html": [ [ "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-hour.html", @@ -182407,6 +182543,12 @@ {} ] ], + "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-valign.html": [ + [ + "/html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-valign.html", + {} + ] + ], "html/semantics/embedded-content/media-elements/user-interface/muted.html": [ [ "/html/semantics/embedded-content/media-elements/user-interface/muted.html", @@ -213095,6 +213237,12 @@ {} ] ], + "svg/extensibility/foreignObject/properties.svg": [ + [ + "/svg/extensibility/foreignObject/properties.svg", + {} + ] + ], "svg/extensibility/interfaces/foreignObject-graphics.svg": [ [ "/svg/extensibility/interfaces/foreignObject-graphics.svg", @@ -236096,10 +236244,6 @@ "f5c79e2a665ef70d7d3abf6dc4fb42dcb453eb78", "testharness" ], - "cookie-store/document_get_set.tentative.html": [ - "3c0eb76fb059743b8628f76b1aa2e15e9fafbb28", - "testharness" - ], "cookie-store/document_has.tentative.html": [ "64941b04dc663c01838112f618cdd8f1a5603c12", "testharness" @@ -236120,6 +236264,10 @@ "d708add276da0fc58b6b628f05bacaa2965795ca", "testharness" ], + "cookie-store/get_set.tentative.window.js": [ + "7439e63ae3e5b06a43ab168ece73123f90712f25", + "testharness" + ], "cookie-store/get_set_get_all.tentative.html": [ "dc66cbf2b2a939179cae29aaeb39cb44eb488e2a", "testharness" @@ -236252,6 +236400,14 @@ "b7bc4516ad4ac7ae1bb572191c0c3932c29eb863", "support" ], + "cookie-store/serviceworker_cookiestore_basic.js": [ + "014e603f394dd9a3394ffef8921c0c870b8577b4", + "support" + ], + "cookie-store/serviceworker_cookiestore_basic.tentative.https.html": [ + "03084278e3856be71bd3bb94c5de2ef53a1a5a88", + "testharness" + ], "cookies/OWNERS": [ "994f3e91756d021ddc53736923353d290df1ecb6", "support" @@ -254664,10 +254820,18 @@ "a2ebae461e59f93107b1abcf88f38fa2e484371c", "reftest" ], + "css/css-display/display-contents-button.html": [ + "31f559d839f47e4034910ecf9224cccb3d44cac4", + "reftest" + ], "css/css-display/display-contents-computed-style.html": [ "bf523ee19c5ff481a3f91f8eb124eb83301738c5", "testharness" ], + "css/css-display/display-contents-details.html": [ + "d1f62084c5adc3ba7a86306704f804d4cbe0428c", + "reftest" + ], "css/css-display/display-contents-dynamic-before-after-001.html": [ "9142d9f1ad5b5e9a5f5705a44c962084f023a3c6", "reftest" @@ -254756,6 +254920,10 @@ "c874f59947d37659e640d4e0abb8a0dc0f03927d", "reftest" ], + "css/css-display/display-contents-fieldset.html": [ + "5532214fa9e6d5b8a6423701760204f96efd65fe", + "reftest" + ], "css/css-display/display-contents-first-letter-001.html": [ "acfaf8f68595c7eb36585309b9d6b0bc5c0ffe41", "reftest" @@ -258065,7 +258233,7 @@ "support" ], "css/css-fonts/font-default-01.html": [ - "f8cacf1d1151773294d278025d2e9e3c859da7ee", + "631cc38f77f522b8f7483313e6f72478048c7f5b", "reftest" ], "css/css-fonts/font-default-02-ref.html": [ @@ -298464,8 +298632,12 @@ "e44be4c30e9c65a4b51972efab2e161f166d58a5", "testharness" ], + "encoding/big5-encoder-expected.txt": [ + "da781afed3b1f5da57531d09b4fdeff6fd548f14", + "support" + ], "encoding/big5-encoder.html": [ - "b9635c43ce159e1961106b039dce0e3d04fade34", + "c5fec0f733b77620267488917cf54554c766801f", "testharness" ], "encoding/eof-shift_jis-ref.html": [ @@ -298504,8 +298676,12 @@ "6f091a64de33492bd17ecbd37f5db0fff9af499a", "testharness" ], + "encoding/gbk-encoder-expected.txt": [ + "9021fe9d14bff1f70c0a2649ac462da6e9170366", + "support" + ], "encoding/gbk-encoder.html": [ - "30bdfc96ffaff0277ceca69aad43d82d5ac691b6", + "d099c6f374df5e68dd44bd6fe6115c415e74e91c", "testharness" ], "encoding/idlharness.html": [ @@ -313680,6 +313856,14 @@ "68ae570e941a5b8993c163a84aca0f758d65ab01", "support" ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/class-bad.vtt": [ + "48b56cffac57d58ed363c6de43123cf46b9a61c4", + "support" + ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/class.vtt": [ + "e3ebad0f6068acc7fd11a5969c1753c4ef86c1b9", + "support" + ], "html/semantics/embedded-content/media-elements/track/track-element/resources/cue-id-error.vtt": [ "e1e8e96b61a5ef48aec96a6c605929f39300e9d9", "support" @@ -313724,6 +313908,14 @@ "db041f1a659ab39530144bb68e0ab76d14ca9b90", "support" ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/entities-wrong.vtt": [ + "9941f3c18ac34d852ab7f882c06d10a874453c14", + "support" + ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/entities.vtt": [ + "5913b038e7d6341b19c21d0bb81008057656d929", + "support" + ], "html/semantics/embedded-content/media-elements/track/track-element/resources/iso2022jp3.vtt": [ "e929f8e1755f72ecae96dd40430bc07c5a4a433c", "support" @@ -313736,6 +313928,14 @@ "eb83dd089934f5e72039eebd57ed17f775408377", "support" ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/markup-bad.vtt": [ + "7caf06d65f3e6c9ba305b4a2b162efbeb68b7a86", + "support" + ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/markup.vtt": [ + "25514f3b659150b7536890cf5bbaff19c57437fe", + "support" + ], "html/semantics/embedded-content/media-elements/track/track-element/resources/metadata-area.vtt": [ "778ac955bd2e01b8c6c8fdf540c99f4513390f5e", "support" @@ -313772,6 +313972,14 @@ "af042c5468830fbdcd9b9c7cbc32eb0c6d660311", "support" ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp-bad.vtt": [ + "6852fb1bfcddce00b4acba93716d7358957a74e5", + "support" + ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/timestamp.vtt": [ + "ed03dac0cac2e0b79c8b98e1e460b24fb7b2daeb", + "support" + ], "html/semantics/embedded-content/media-elements/track/track-element/resources/timings-hour-error.vtt": [ "e2cf1290a06473ac1592e8da4d8261d392f14606", "support" @@ -313808,6 +314016,18 @@ "b15aef44ae1726c362448bc561899c7dc554a767", "support" ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/valign-bad.vtt": [ + "3517a6189833600e6db45a8c7fed79d38859b1c1", + "support" + ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/valign-ltr.vtt": [ + "2c1f48f5098da305b6fe6c362a94c4a2a5e13c38", + "support" + ], + "html/semantics/embedded-content/media-elements/track/track-element/resources/valign.vtt": [ + "357f4306f5b5c83b712d0a0bbb098827c3802196", + "support" + ], "html/semantics/embedded-content/media-elements/track/track-element/resources/webvtt-file.vtt": [ "943c4ca7d7ba197815ad5732222558e30195b022", "support" @@ -313849,7 +314069,7 @@ "testharness" ], "html/semantics/embedded-content/media-elements/track/track-element/track-helpers.js": [ - "fe9bae0ff27ade387e103628dd35cd6989129254", + "b84cd1d9f96ee9b00cef2bd219e6da5b1ba1df8b", "support" ], "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-align-positioning.html": [ @@ -313872,6 +314092,10 @@ "26343f09d663d1558881507f89eecc606304b41f", "testharness" ], + "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-class-markup.html": [ + "8876395c46181acafb7712b1fcdff7cae28c0b18", + "testharness" + ], "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-cue-identifiers.html": [ "d21e8cd62cc5a7bf9275b2f46282cd3f73714c21", "testharness" @@ -313888,6 +314112,10 @@ "5f91fd3c078343aee9ee72c1b60bf8a8f82682e2", "testharness" ], + "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-entities.html": [ + "b995f43c4dfef791a95bc0dfcd30721e955fce85", + "testharness" + ], "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-header-comment.html": [ "3e83c514cb2d18b2238f03e3d85a21f69a60d5c0", "testharness" @@ -313900,6 +314128,10 @@ "ef8442f73c4aae5728a8790d6a7dbc075bb09a25", "testharness" ], + "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-markup.html": [ + "6d8f7b9e8e3cb87581844b5dd61e46cc508b616c", + "testharness" + ], "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-newlines.html": [ "24d79495469c698e1e0296b503e44a3ee6b5db34", "testharness" @@ -313916,6 +314148,10 @@ "25f3286199d565d58b3e4545a5f3cbb212541a34", "testharness" ], + "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timestamp.html": [ + "d18cd2431e189249d1210ba5ef87c081f3d355ee", + "testharness" + ], "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-timings-hour.html": [ "b52de7d267cce4c480353c188173c6bbc5e3e70e", "testharness" @@ -313928,6 +314164,10 @@ "65241920becf512c35f78b335de90c00af03195d", "testharness" ], + "html/semantics/embedded-content/media-elements/track/track-element/track-webvtt-valign.html": [ + "4f6e049d97dc81065df13e66e40cf945ff0914dd", + "testharness" + ], "html/semantics/embedded-content/media-elements/user-interface/muted.html": [ "74deefbbc4b8f96ff4856db1c32c6428183cc040", "testharness" @@ -344428,6 +344668,10 @@ "ce9e3471676d5a50b91f6b274d648b481e509223", "support" ], + "svg/extensibility/foreignObject/properties.svg": [ + "946999ca1917a5069103c025197c2903ab0bae64", + "testharness" + ], "svg/extensibility/interfaces/foreignObject-graphics.svg": [ "16a7ef4c64dab3706120a2221dd6bec5ca8e9062", "testharness"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/cookie-store/document_get_set.tentative.html b/third_party/WebKit/LayoutTests/external/wpt/cookie-store/get_set.tentative.window.js similarity index 64% rename from third_party/WebKit/LayoutTests/external/wpt/cookie-store/document_get_set.tentative.html rename to third_party/WebKit/LayoutTests/external/wpt/cookie-store/get_set.tentative.window.js index e90d0e5a..1fa834a 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/cookie-store/document_get_set.tentative.html +++ b/third_party/WebKit/LayoutTests/external/wpt/cookie-store/get_set.tentative.window.js
@@ -1,11 +1,3 @@ -<!doctype html> -<meta charset="utf-8"> -<title>Async Cookies: cookieStore.get() sees cookieStore.set() cookie</title> -<link rel="help" href="https://github.com/WICG/cookie-store"> -<link rel="author" href="pwnall@chromium.org" title="Victor Costan"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script> 'use strict'; // Workaround because add_cleanup doesn't support async functions yet. @@ -27,5 +19,3 @@ await async_cleanup(() => cookieStore.delete('cookie-name')); }, 'cookieStore.get returns the cookie written by cookieStore.set'); - -</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/cookie-store/serviceworker_cookiestore_basic.js b/third_party/WebKit/LayoutTests/external/wpt/cookie-store/serviceworker_cookiestore_basic.js new file mode 100644 index 0000000..13b973e1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/cookie-store/serviceworker_cookiestore_basic.js
@@ -0,0 +1,9 @@ +self.GLOBAL = { + isWindow: function() { return false; }, + isWorker: function() { return true; }, +}; +importScripts("/resources/testharness.js"); + +importScripts("get_set.tentative.window.js"); + +done();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/cookie-store/serviceworker_cookiestore_basic.tentative.https.html b/third_party/WebKit/LayoutTests/external/wpt/cookie-store/serviceworker_cookiestore_basic.tentative.https.html new file mode 100644 index 0000000..0c3f6819 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/cookie-store/serviceworker_cookiestore_basic.tentative.https.html
@@ -0,0 +1,20 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Async Cookies: cookieStore.get() sees cookieStore.set() cookie in ServiceWorker</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +'use strict'; + +(async () => { + const scope = 'does/not/exist'; + + let registration = await navigator.serviceWorker.getRegistration(scope); + if (registration) + await registration.unregister(); + registration = await navigator.serviceWorker.register( + 'serviceworker_cookiestore_basic.js', {scope}); + + fetch_tests_from_worker(registration.installing); +})(); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/font-default-01.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/font-default-01.html index c9045ed..99fc58b 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/font-default-01.html +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/font-default-01.html
@@ -3,7 +3,7 @@ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>CSS Test: font default features</title> <link rel="author" title="Chris Lilley" href="chris@w3.org"> -<link rel="help" href="hhttps://www.w3.org/TR/css-fonts-3/#default-features"> +<link rel="help" href="https://www.w3.org/TR/css-fonts-3/#default-features"> <link rel="match" href="font-default-01-ref.html"> <meta name="assert" content="Required ligatures, common ligatures and contextual forms must be enabled by default (OpenType features: rlig, liga, clig, calt), along with localized forms (OpenType feature: locl), and features required for proper display of composed characters and marks (OpenType features: ccmp, mark, mkmk)."> <style>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/big5-encoder-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/encoding/big5-encoder-expected.txt new file mode 100644 index 0000000..af399bc --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/big5-encoder-expected.txt
@@ -0,0 +1,16 @@ +This is a testharness.js-based test. +PASS big5 encoder: very basic +FAIL big5 encoder: Highest-pointer BMP character excluded from encoder assert_equals: expected "X&%2340614;X" but got "X%26%2340614%3BX" +FAIL big5 encoder: Highest-pointer character excluded from encoder assert_equals: expected "X&%23156267;X" but got "X%26%23156267%3BX" +PASS big5 encoder: Lowest-pointer character included in encoder +PASS big5 encoder: Euro; the highest-pointer character before a range of 30 unmapped pointers +PASS big5 encoder: The lowest-pointer character after the range of 30 unmapped pointers +PASS big5 encoder: The highest-pointer character before a range of 41 unmapped pointers +PASS big5 encoder: The lowest-pointer character after the range of 41 unmapped pointers +PASS big5 encoder: The last character in the index +FAIL big5 encoder: The canonical BMP test character that is not in the index assert_equals: expected "X&%239731;X" but got "X%26%239731%3BX" +FAIL big5 encoder: The canonical astral test character that is not in the index assert_equals: expected "X&%23128169;X" but got "X%26%23128169%3BX" +PASS big5 encoder: A Plane 2 character whose low 16 bits match a BMP character that has a lower pointer +PASS big5 encoder: A duplicate-mapped code point that prefers the highest pointer in the encoder +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/big5-encoder.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/big5-encoder.html index 7260b6b..58d60d5 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/encoding/big5-encoder.html +++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/big5-encoder.html
@@ -15,8 +15,8 @@ encode("ab", "ab", "very basic") // edge cases - encode("\u9EA6", "%26%2340614%3B", "Highest-pointer BMP character excluded from encoder"); - encode("\uD858\uDE6B", "%26%23156267%3B", "Highest-pointer character excluded from encoder"); + encode("\u9EA6", "&%2340614;", "Highest-pointer BMP character excluded from encoder"); + encode("\uD858\uDE6B", "&%23156267;", "Highest-pointer character excluded from encoder"); encode("\u3000", "%A1@", "Lowest-pointer character included in encoder"); encode("\u20AC", "%A3%E1", "Euro; the highest-pointer character before a range of 30 unmapped pointers"); encode("\u4E00", "%A4@", "The lowest-pointer character after the range of 30 unmapped pointers"); @@ -24,8 +24,8 @@ encode("\uFFE2", "%C8%CD", "The lowest-pointer character after the range of 41 unmapped pointers"); encode("\u79D4", "%FE%FE", "The last character in the index"); // not in index - encode("\u2603", "%26%239731%3B", "The canonical BMP test character that is not in the index"); - encode("\uD83D\uDCA9", "%26%23128169%3B", "The canonical astral test character that is not in the index"); + encode("\u2603", "&%239731;", "The canonical BMP test character that is not in the index"); + encode("\uD83D\uDCA9", "&%23128169;", "The canonical astral test character that is not in the index"); // duplicate low bits encode("\uD840\uDFB5", "%FDj", "A Plane 2 character whose low 16 bits match a BMP character that has a lower pointer"); // prefer last
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/gbk-encoder-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/encoding/gbk-encoder-expected.txt new file mode 100644 index 0000000..c4b35d1 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/gbk-encoder-expected.txt
@@ -0,0 +1,9 @@ +This is a testharness.js-based test. +PASS gbk encoder: very basic +PASS gbk encoder: Euro +PASS gbk encoder: character +PASS gbk encoder: PUA +PASS gbk encoder: PUA #2 +FAIL gbk encoder: poo assert_equals: expected "&%23128169;" but got "%26%23128169%3B" +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/encoding/gbk-encoder.html b/third_party/WebKit/LayoutTests/external/wpt/encoding/gbk-encoder.html index a6074f97..90d0824 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/encoding/gbk-encoder.html +++ b/third_party/WebKit/LayoutTests/external/wpt/encoding/gbk-encoder.html
@@ -17,5 +17,5 @@ encode("\u4E02", "%81@", "character") encode("\uE4C6", "%A1@", "PUA") encode("\uE4C5", "%FE%FE", "PUA #2") - encode("\ud83d\udca9", "%26%23128169%3B", "poo") + encode("\ud83d\udca9", "&%23128169;", "poo") </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/preload/modulepreload.html b/third_party/WebKit/LayoutTests/external/wpt/preload/modulepreload.html index 1663176..addd67d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/preload/modulepreload.html +++ b/third_party/WebKit/LayoutTests/external/wpt/preload/modulepreload.html
@@ -53,8 +53,8 @@ link.rel = 'modulepreload'; link.href = 'resources/module1.js'; return attachAndWaitForLoad(link).then(() => { - // Currently, modulepreload doesn't perform submodules fetch. verifyNumberOfDownloads('resources/module1.js', 1); + // The load event fires before (optional) submodules fetch. verifyNumberOfDownloads('resources/module2.js', 0); var script = document.createElement('script');
diff --git a/third_party/WebKit/LayoutTests/http/tests/bluetooth/https/requestDevice/cross-origin-iframe.html b/third_party/WebKit/LayoutTests/http/tests/bluetooth/https/requestDevice/cross-origin-iframe.html index b121f05..719ac2ca 100644 --- a/third_party/WebKit/LayoutTests/http/tests/bluetooth/https/requestDevice/cross-origin-iframe.html +++ b/third_party/WebKit/LayoutTests/http/tests/bluetooth/https/requestDevice/cross-origin-iframe.html
@@ -4,34 +4,32 @@ <script src="/js-test-resources/testdriver.js"></script> <script src="/js-test-resources/testdriver-vendor.js"></script> <script src="/js-test-resources/bluetooth/bluetooth-helpers.js"></script> -<script src="/js-test-resources/bluetooth/bluetooth-fake-adapter.js"></script> <body> <script> 'use strict'; const test_desc = 'Request device from a unique origin. ' + 'Should reject with SecurityError.'; - let iframe = document.createElement('iframe'); -async_test(test => - setBluetoothFakeAdapter('HeartRateAdapter') - // 1. Load the iframe. - .then(() => new Promise(resolve => { - iframe.src = 'https://localhost:8443/js-test-resources/bluetooth/requestDevice-in-iframe.html'; - document.body.appendChild(iframe); - iframe.addEventListener('load', resolve); - })) - // 2. Request the device from the iframe. - .then(() => { - callWithTrustedClick(() => { - iframe.contentWindow.postMessage('Go', '*'); - }); +bluetooth_test(() => setUpConnectableHealthThermometerDevice() + // 1. Load the iframe. + .then(() => new Promise(resolve => { + iframe.src = 'https://localhost:8443/js-test-resources/bluetooth/' + + 'requestDevice-in-iframe.html'; + document.body.appendChild(iframe); + iframe.addEventListener('load', resolve); + })) + // 2. Request the device from the iframe. + .then(() => new Promise(resolve => { + callWithTrustedClick(() => { + iframe.contentWindow.postMessage('Go', '*'); + }); - window.onmessage = messageEvent => test.step(() => { - assert_equals(messageEvent.data, 'SecurityError: requestDevice() ' + - 'called from cross-origin iframe.'); - test.done(); - }); -}), test_desc); + window.onmessage = messageEvent => { + assert_equals(messageEvent.data, 'SecurityError: requestDevice() ' + + 'called from cross-origin iframe.'); + resolve(); + } + })), test_desc); </script> </body>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-iframe-manifests.js b/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-iframe-manifests.js index 10f0d3c..349246f 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-iframe-manifests.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-iframe-manifests.js
@@ -6,6 +6,9 @@ TestRunner.addResult( `Tests that application cache model keeps track of manifest urls and statuses correctly. https://bugs.webkit.org/show_bug.cgi?id=64581\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); await TestRunner.loadHTML(` <p>Tests that application cache model keeps track of manifest urls and statuses correctly.</p>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-manifest-with-non-existing-file.js b/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-manifest-with-non-existing-file.js index c513cdf9..dc612d8 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-manifest-with-non-existing-file.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-manifest-with-non-existing-file.js
@@ -6,6 +6,9 @@ TestRunner.addResult( `Tests that application cache model keeps track of manifest urls and statuses correctly when there is a non existing file listed in manifest. https://bugs.webkit.org/show_bug.cgi?id=64581\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); await TestRunner.loadHTML(` <p>Tests that application cache model keeps track of manifest urls and statuses correctly when there is a non existing file listed in manifest.</p>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-swap.js b/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-swap.js index 4a592a9..f8c0f151 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-swap.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/appcache/appcache-swap.js
@@ -6,6 +6,9 @@ TestRunner.addResult( `Tests that application cache model keeps track of manifest urls and statuses correctly after UPDATEREADY event and swapCache() call.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.loadModule('network_test_runner'); await TestRunner.showPanel('resources'); await TestRunner.loadHTML(`
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-on-navigation.js b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-on-navigation.js index 93adb5f5..2a508bb 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-on-navigation.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-on-navigation.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests Application Panel response to a main frame navigation.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.loadModule('console_test_runner'); await TestRunner.showPanel('resources');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-resource-preview.js b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-resource-preview.js index 20cf572..0161c8c 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-resource-preview.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-resource-preview.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests Application Panel preview for resources of different types.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.loadModule('console_test_runner'); await TestRunner.showPanel('resources'); await TestRunner.loadHTML(`
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-selection-on-reload.js b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-selection-on-reload.js index d10b69d..2ccb2c8 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-selection-on-reload.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-selection-on-reload.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests Application Panel response to a main frame navigation.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.loadModule('console_test_runner'); await TestRunner.showPanel('resources');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-websql.js b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-websql.js index 1f3bf98..3e2750a 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-websql.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/resources-panel-websql.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests Application Panel WebSQL support.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.loadModule('console_test_runner'); await TestRunner.showPanel('resources'); await TestRunner.evaluateInPagePromise(`
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/storage-view-reports-quota.js b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/storage-view-reports-quota.js index 365fbc3..ce21f4787 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/storage-view-reports-quota.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/application-panel/storage-view-reports-quota.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests quota reporting.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.loadModule('console_test_runner'); await TestRunner.showPanel('resources');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-data.js b/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-data.js index cf38806..09439e0 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-data.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-data.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests that cache data is correctly populated in the Inspector.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); var cacheStorageModel = TestRunner.mainTarget.model(SDK.ServiceWorkerCacheModel);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-deletion.js b/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-deletion.js index 6455187..4d3774a 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-deletion.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-deletion.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests that cache data is correctly deleted by the inspector.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); var cacheStorageModel = TestRunner.mainTarget.model(SDK.ServiceWorkerCacheModel);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-entry-deletion.js b/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-entry-deletion.js index 390118d..65cc7aa 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-entry-deletion.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-entry-deletion.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests that cache entry data is correctly deleted by the inspector.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); var cacheStorageModel = TestRunner.mainTarget.model(SDK.ServiceWorkerCacheModel);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-live-update-cache-content.js b/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-live-update-cache-content.js index f76edce..0b061761 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-live-update-cache-content.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-live-update-cache-content.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests that cache view updates when the cache is changed.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); var cacheStorageModel = TestRunner.mainTarget.model(SDK.ServiceWorkerCacheModel);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-live-update-list.js b/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-live-update-list.js index 841719c..c32ab30 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-live-update-list.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-live-update-list.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests that the cache storage list live updates.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); var cacheStorageModel = TestRunner.mainTarget.model(SDK.ServiceWorkerCacheModel);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-names.js b/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-names.js index d3d5451f2..955b5bb 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-names.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-names.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests that cache names are correctly loaded and displayed in the inspector.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); var cacheStorageModel = TestRunner.mainTarget.model(SDK.ServiceWorkerCacheModel);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-track-valid-origin.js b/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-track-valid-origin.js index 7a9b14fa..bd46bc6 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-track-valid-origin.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/cache-storage/cache-track-valid-origin.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests that cache storage live update only tracks valid security origins.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); var cacheStorageModel = TestRunner.mainTarget.model(SDK.ServiceWorkerCacheModel);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/geolocation-emulation-tests-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/geolocation-emulation-tests-expected.txt index 48384994..4a00ebd 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/geolocation-emulation-tests-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/geolocation-emulation-tests-expected.txt
@@ -17,5 +17,8 @@ geolocation-emulation-tests.js:41 Latitude: 50 Longitude: 100 Running: testTimestampOfOverridenPosition -geolocation-emulation-tests.js:59 PASSED +geolocation-emulation-tests.js:79 PASSED + +Running: testNoOverride +Override was cleared correctly.
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/geolocation-emulation-tests.js b/third_party/WebKit/LayoutTests/http/tests/devtools/geolocation-emulation-tests.js index c79cc30d..46e8e41 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/geolocation-emulation-tests.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/geolocation-emulation-tests.js
@@ -51,6 +51,26 @@ navigator.geolocation.getCurrentPosition(testSuccess, testFailed); } + function getPositionPromise() + { + return new Promise((resolve, reject) => { + function testSuccess(position) + { + if (position && position.coords) + resolve("Latitude: " + position.coords.latitude + " Longitude: " + position.coords.longitude); + else + resolve("Unexpected error occured. Test failed."); + } + + function testFailed(error) + { + resolve(serializeGeolocationError(error)); + } + + navigator.geolocation.getCurrentPosition(testSuccess, testFailed); + }); + } + function overridenTimestampGeolocation() { function testSuccess(position) @@ -78,10 +98,18 @@ }); } + var positionBeforeOverride; + TestRunner.runTestSuite([ function testPermissionGranted(next) { - consoleSniffAndDump(next); + consoleSniffAndDump(savePositionBeforeOverride); TestRunner.evaluateInPage('grantGeolocationPermission()'); + + async function savePositionBeforeOverride() { + positionBeforeOverride = await TestRunner.evaluateInPageAsync('getPositionPromise()'); + Console.ConsoleView.clearConsole(); + next(); + } }, function testGeolocationUnavailable(next) { @@ -112,5 +140,15 @@ consoleSniffAndDump(next); TestRunner.evaluateInPage('overridenTimestampGeolocation()'); }, + + async function testNoOverride(next) { + TestRunner.EmulationAgent.clearGeolocationOverride(); + var positionString = await TestRunner.evaluateInPageAsync('getPositionPromise()'); + if (positionString === positionBeforeOverride) + TestRunner.addResult('Override was cleared correctly.'); + else + TestRunner.addResult('Position differs from value before override.'); + next(); + } ]); })();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/database-data.js b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/database-data.js index e9ad0540..b7d7312 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/database-data.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/database-data.js
@@ -6,6 +6,8 @@ TestRunner.addResult( `Tests that data is correctly loaded by IndexedDBModel from IndexedDB object store and index.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); var indexedDBModel = ApplicationTestRunner.createIndexedDBModel(); var mainFrameId = TestRunner.resourceTreeModel.mainFrame.id;
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/database-names.js b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/database-names.js index 1d8e3a1c..e7d8771 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/database-names.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/database-names.js
@@ -5,6 +5,8 @@ (async function() { TestRunner.addResult(`Tests that database names are correctly loaded and saved in IndexedDBModel.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); var indexedDBModel = ApplicationTestRunner.createIndexedDBModel(); var mainFrameId = TestRunner.resourceTreeModel.mainFrame.id;
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/database-refresh-view.js b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/database-refresh-view.js index 6a02c96..906a04659 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/database-refresh-view.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/database-refresh-view.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests refreshing the database information and data views.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.loadModule('console_test_runner'); await TestRunner.showPanel('resources');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/database-structure.js b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/database-structure.js index ee8693f..1b1f5b1 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/database-structure.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/database-structure.js
@@ -5,6 +5,8 @@ (async function() { TestRunner.addResult(`Tests that database names are correctly loaded and saved in IndexedDBModel.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); var indexedDBModel = ApplicationTestRunner.createIndexedDBModel(); var mainFrameId = TestRunner.resourceTreeModel.mainFrame.id;
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/delete-entry.js b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/delete-entry.js index f4a177a..11f6380 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/delete-entry.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/delete-entry.js
@@ -5,6 +5,8 @@ (async function() { TestRunner.addResult(`Tests object store and index entry deletion.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); function dumpObjectStore(treeElement) { TestRunner.addResult(` Index: ${treeElement.title}`);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/live-update-indexeddb-content.js b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/live-update-indexeddb-content.js index 5152007..906e3772 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/live-update-indexeddb-content.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/live-update-indexeddb-content.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests that the IndexedDB database content live updates.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); let indexedDBModel = TestRunner.mainTarget.model(Resources.IndexedDBModel);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/live-update-indexeddb-list.js b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/live-update-indexeddb-list.js index 92d19ac..f82fe352 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/live-update-indexeddb-list.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/live-update-indexeddb-list.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests that the IndexedDB database list live updates.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); let indexedDBModel = TestRunner.mainTarget.model(Resources.IndexedDBModel);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/resources-panel.js b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/resources-panel.js index f84802d..59674c0 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/resources-panel.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/resources-panel.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests IndexedDB tree element on resources panel.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.loadModule('console_test_runner'); var mainFrameId = TestRunner.resourceTreeModel.mainFrame.id;
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/track-valid-origin.js b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/track-valid-origin.js index c09ac33..64ebf3d 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/track-valid-origin.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/track-valid-origin.js
@@ -5,6 +5,8 @@ (async function() { TestRunner.addResult(`Tests that IndexedDB live update only tracks valid security origins.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); let indexedDBModel = TestRunner.mainTarget.model(Resources.IndexedDBModel); let invalidOrigins = ['http', 'test://fake', 'test://fake.origin.com', 'chrome://test'];
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/transaction-promise-console.js b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/transaction-promise-console.js index 286953ab..1382978 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/transaction-promise-console.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/transaction-promise-console.js
@@ -6,6 +6,9 @@ TestRunner.addResult( `Ensure transactions created within Promise callbacks are not deactivated due to console activity\n`); await TestRunner.loadModule('console_test_runner'); + await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); testRunner.waitUntilDone(); testRunner.showWebInspector();
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/upgrade-events.js b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/upgrade-events.js index 1aabd15..96445538 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/upgrade-events.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/indexeddb/upgrade-events.js
@@ -5,6 +5,8 @@ (async function() { TestRunner.addResult(`Tests that deleted databases do not get recreated.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); var indexedDBModel = ApplicationTestRunner.createIndexedDBModel(); var mainFrameId = TestRunner.resourceTreeModel.mainFrame.id;
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/load-resource-for-frontend-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/network/load-resource-for-frontend-expected.txt index 0de393c..f7b741c 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/network/load-resource-for-frontend-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/load-resource-for-frontend-expected.txt
@@ -2,19 +2,19 @@ Running: testNetworkResourceNonCached -Loading resource from http://localhost:8080/inspector/network/resources/resource.php +Loading resource from http://localhost:8080/devtools/network/resources/resource.php Success: 200 Logged headers: cache-control, expires, pragma Content: "Hello world" Running: testNetworkResourceCached -Loading resource from http://localhost:8080/inspector/network/resources/resource.php?cached=1 +Loading resource from http://localhost:8080/devtools/network/resources/resource.php?cached=1 Success: 200 Logged headers: cache-control, expires, last-modified Content: "Hello world" Running: testNetworkResourceIfModifiedSince -Loading resource from http://localhost:8080/inspector/network/resources/resource.php?cached=1 +Loading resource from http://localhost:8080/devtools/network/resources/resource.php?cached=1 Success: 304 Logged headers: Content: "" @@ -26,7 +26,7 @@ Content: "" Running: testResourceWithCookie -Loading resource from http://127.0.0.1:8000/inspector/network/resources/print-cookie.php +Loading resource from http://127.0.0.1:8000/devtools/network/resources/print-cookie.php Success: 200 Logged headers: cache-control, expires, pragma Content: "Cookie value: TestCookieValue."
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/load-resource-for-frontend.js b/third_party/WebKit/LayoutTests/http/tests/devtools/network/load-resource-for-frontend.js index 460dadd4..dd1a0eb 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/network/load-resource-for-frontend.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/load-resource-for-frontend.js
@@ -32,16 +32,16 @@ TestRunner.runTestSuite([ function testNetworkResourceNonCached(next) { - testLoadForURL('http://localhost:8080/inspector/network/resources/resource.php', undefined, next); + testLoadForURL('http://localhost:8080/devtools/network/resources/resource.php', undefined, next); }, function testNetworkResourceCached(next) { - testLoadForURL('http://localhost:8080/inspector/network/resources/resource.php?cached=1', undefined, next); + testLoadForURL('http://localhost:8080/devtools/network/resources/resource.php?cached=1', undefined, next); }, function testNetworkResourceIfModifiedSince(next) { testLoadForURL( - 'http://localhost:8080/inspector/network/resources/resource.php?cached=1', + 'http://localhost:8080/devtools/network/resources/resource.php?cached=1', {'if-modified-since': new Date().toUTCString()}, next); }, @@ -51,10 +51,10 @@ function testResourceWithCookie(next) { NetworkTestRunner.makeSimpleXHR( - 'GET', 'http://127.0.0.1:8000/inspector/network/resources/set-cookie.php', false, callback); + 'GET', 'http://127.0.0.1:8000/devtools/network/resources/set-cookie.php', false, callback); function callback() { - testLoadForURL('http://127.0.0.1:8000/inspector/network/resources/print-cookie.php', undefined, next); + testLoadForURL('http://127.0.0.1:8000/devtools/network/resources/print-cookie.php', undefined, next); } } ]);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-disable-cache-cors-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-disable-cache-cors-expected.txt index 0b3a552..ba02386 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-disable-cache-cors-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-disable-cache-cors-expected.txt
@@ -1,9 +1,9 @@ Tests that preflight OPTIONS is always sent if 'Disable cache' is checked, and that network instrumentation does not produce errors for redirected preflights. -OPTIONS: http://localhost:8080/inspector/network/resources/cors-redirect.cgi -OPTIONS: http://localhost:8080/inspector/network/resources/cors-redirect.cgi -OPTIONS: http://localhost:8000/inspector/network/resources/cors.cgi -POST: http://localhost:8000/inspector/network/resources/cors.cgi -OPTIONS: http://localhost:8000/inspector/network/resources/cors.cgi -POST: http://localhost:8000/inspector/network/resources/cors.cgi +OPTIONS: http://localhost:8080/devtools/network/resources/cors-redirect.cgi +OPTIONS: http://localhost:8080/devtools/network/resources/cors-redirect.cgi +OPTIONS: http://localhost:8000/devtools/network/resources/cors.cgi +POST: http://localhost:8000/devtools/network/resources/cors.cgi +OPTIONS: http://localhost:8000/devtools/network/resources/cors.cgi +POST: http://localhost:8000/devtools/network/resources/cors.cgi
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-disable-cache-cors.js b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-disable-cache-cors.js index 50f3603..1958f8c 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-disable-cache-cors.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-disable-cache-cors.js
@@ -17,7 +17,7 @@ if (xhr.readyState === XMLHttpRequest.DONE) callback(); }; - xhr.open("POST", "http://localhost:8000/inspector/network/resources/cors.cgi"); + xhr.open("POST", "http://localhost:8000/devtools/network/resources/cors.cgi"); xhr.setRequestHeader("Content-Type", "application/xml"); xhr.send("<xml></xml>"); } @@ -40,9 +40,9 @@ `); NetworkTestRunner.makeFetch( - 'http://localhost:8080/inspector/network/resources/cors-redirect.cgi', {headers: {'x-test': 'redirect'}}, + 'http://localhost:8080/devtools/network/resources/cors-redirect.cgi', {headers: {'x-test': 'redirect'}}, function() {}); - NetworkTestRunner.makeFetch('http://localhost:8080/inspector/network/resources/cors-redirect.cgi', {}, disableCache); + NetworkTestRunner.makeFetch('http://localhost:8080/devtools/network/resources/cors-redirect.cgi', {}, disableCache); async function disableCache() { await TestRunner.NetworkAgent.setCacheDisabled(true);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-status-non-http-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-status-non-http-expected.txt index 23098ec..a966e18 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-status-non-http-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-status-non-http-expected.txt
@@ -1,6 +1,6 @@ Test network status of non http request. -network-test.js:200 OKFinished +network-status-non-http.js:200 OKFinished non-existent-file.js:404 Not Found(failed) data:application/ja…:200 OKFinished
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-status-non-http.js b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-status-non-http.js index 4af001e..38ccef34 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-status-non-http.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/network-status-non-http.js
@@ -16,7 +16,7 @@ function loadResources() { - addScriptElement("../../inspector/network-test.js"); + addScriptElement("network-status-non-http.js"); addScriptElement("non-existent-file.js"); // Test that data-url doesn't appear in network panel. @@ -25,7 +25,7 @@ `); await TestRunner.NetworkAgent.setCacheDisabled(true); - var requestsToWatch = /\/network-test\.js$|\/non-existent-file.js$|^data:application\/javascript,|/; + var requestsToWatch = /\/network-status-non-http\.js$|\/non-existent-file.js$|^data:application\/javascript,|/; var seenRequests = 0; function dumpRequests() {
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/warning-for-long-cookie-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/network/warning-for-long-cookie-expected.txt index 084a6da..23b6570 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/network/warning-for-long-cookie-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/warning-for-long-cookie-expected.txt
@@ -1,6 +1,6 @@ Checks that we show warning message for long cookie. -VM:58 Set-Cookie header is ignored in response from url: http://127.0.0.1:8000/inspector/network/resources/set-cookie.php?length=4097. Cookie length should be less than or equal to 4096 characters. +VM:58 Set-Cookie header is ignored in response from url: http://127.0.0.1:8000/devtools/network/resources/set-cookie.php?length=4097. Cookie length should be less than or equal to 4096 characters. makeFetch @ VM:58 (anonymous) @ VM:1
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/network/warning-for-long-cookie.js b/third_party/WebKit/LayoutTests/http/tests/devtools/network/warning-for-long-cookie.js index 3563b493..291f5117 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/network/warning-for-long-cookie.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/network/warning-for-long-cookie.js
@@ -9,11 +9,11 @@ await TestRunner.showPanel('network'); NetworkTestRunner.makeFetch( - 'http://127.0.0.1:8000/inspector/network/resources/set-cookie.php?length=4096', {}, step1); + 'http://127.0.0.1:8000/devtools/network/resources/set-cookie.php?length=4096', {}, step1); function step1() { NetworkTestRunner.makeFetch( - 'http://127.0.0.1:8000/inspector/network/resources/set-cookie.php?length=4097', {}, dumpMessages); + 'http://127.0.0.1:8000/devtools/network/resources/set-cookie.php?length=4097', {}, dumpMessages); } function dumpMessages() {
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/resource-parameters-ipv6-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/resource-parameters-ipv6-expected.txt index 6db01b9..95c10794 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/resource-parameters-ipv6-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/resource-parameters-ipv6-expected.txt
@@ -5,6 +5,7 @@ cache : { } connection : <string> + pageref : "page_1" request : { bodySize : <number> cookies : [
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/resource-parameters-ipv6.js b/third_party/WebKit/LayoutTests/http/tests/devtools/resource-parameters-ipv6.js index af49fa0..2ab9f78 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/resource-parameters-ipv6.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/resource-parameters-ipv6.js
@@ -5,20 +5,21 @@ (async function() { TestRunner.addResult(`Tests that resources panel shows form data parameters.\n`); await TestRunner.loadModule('network_test_runner'); - await TestRunner.loadHTML(` - <form target="target-iframe" method="POST" action="http://[::1]:8000/devtools/resources/post-target.cgi?queryParam1=queryValue1&queryParam2=#fragmentParam1=fragmentValue1&fragmentParam2="> + await TestRunner.navigatePromise('http://[::1]:8000/devtools/resources/inspected-page.html'); + await TestRunner.evaluateInPagePromise(` + document.write(\`<form target="target-iframe" method="POST" action="http://[::1]:8000/devtools/resources/post-target.cgi?queryParam1=queryValue1&queryParam2=#fragmentParam1=fragmentValue1&fragmentParam2="> <input name="formParam1" value="formValue1"> <input name="formParam2"> <input id="submit" type="submit"> </form> <iframe name="target-iframe"></iframe> - `); - await TestRunner.evaluateInPagePromise(` + <script> function submit() { document.getElementById("submit").click(); } - `); + </script> + \`)`); TestRunner.evaluateInPage('submit()'); TestRunner.networkManager.addEventListener(SDK.NetworkManager.Events.RequestFinished, onRequestFinished);
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/lazy-addeventlisteners.js b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/lazy-addeventlisteners.js index ec0ea75..5c682bb7 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/lazy-addeventlisteners.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/lazy-addeventlisteners.js
@@ -7,6 +7,9 @@ `Tests that a warning is shown in the console if addEventListener is called after initial evaluation of the service worker script.\n`); await TestRunner.loadModule('console_test_runner'); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); var scriptURL = 'http://127.0.0.1:8000/devtools/service-workers/resources/service-worker-lazy-addeventlistener.js';
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-agents.js b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-agents.js index 257e3da..53139fc1 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-agents.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-agents.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests the way service workers don't enable DOM agent and does enable Debugger agent.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); var scriptURL = 'http://127.0.0.1:8000/devtools/service-workers/resources/service-worker-empty.js';
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-manager.js b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-manager.js index 4db9482..24791cd65 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-manager.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-manager.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests the way service worker manager manages targets.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); var scriptURL = 'http://127.0.0.1:8000/devtools/service-workers/resources/service-worker-empty.js';
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-network-fetch-blocked.js b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-network-fetch-blocked.js index 92e65de..23b0e72 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-network-fetch-blocked.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-network-fetch-blocked.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests blocking fetch in Service Workers.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.loadModule('console_test_runner'); await TestRunner.loadModule('network_test_runner'); await TestRunner.showPanel('resources');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-network-fetch.js b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-network-fetch.js index 06afa0e..2a03433 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-network-fetch.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-network-fetch.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests fetch in Service Workers.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.loadModule('console_test_runner'); await TestRunner.loadModule('network_test_runner'); await TestRunner.showPanel('resources');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-pause.js b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-pause.js index bd6ee96..3850bd94 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-pause.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-pause.js
@@ -6,6 +6,9 @@ TestRunner.addResult(`Tests that we can pause in service worker.\n`); await TestRunner.loadModule('sources_test_runner'); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); var scriptURL = 'http://127.0.0.1:8000/devtools/service-workers/resources/service-worker-debugger.js';
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-v8-cache.js b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-v8-cache.js index 67b9ccc..17fc2d1 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-v8-cache.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-worker-v8-cache.js
@@ -6,6 +6,9 @@ TestRunner.addResult(`Tests V8 cache information of Service Worker Cache Storage in timeline\n`); await TestRunner.loadModule('performance_test_runner'); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); await TestRunner.showPanel('timeline'); await TestRunner.evaluateInPagePromise(`
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-bypass-for-network-cors.js b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-bypass-for-network-cors.js index fa26fb6..bb74e50 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-bypass-for-network-cors.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-bypass-for-network-cors.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests "Bypass for network" checkbox works with CORS requests. crbug.com/771742\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); await TestRunner.loadHTML(` <p>Tests "Bypass for network" checkbox works with CORS requests. crbug.com/771742</p>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-bypass-for-network-navigation.js b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-bypass-for-network-navigation.js index 9092596..0d2b3396b 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-bypass-for-network-navigation.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-bypass-for-network-navigation.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests "Bypass for network" checkbox works with navigations. crbug.com/746220\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); await TestRunner.loadHTML(` <p>Tests "Bypass for network" checkbox works with navigations. crbug.com/746220</p>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-bypass-for-network-redirect.js b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-bypass-for-network-redirect.js index 7c2fd01b..8f88649a 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-bypass-for-network-redirect.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-bypass-for-network-redirect.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests "Bypass for network" checkbox with redirection doesn't cause crash.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.loadModule('console_test_runner'); await TestRunner.showPanel('resources'); await TestRunner.loadHTML(`
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-force-update-on-page-load.js b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-force-update-on-page-load.js index d7e35a7..3f36bab 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-force-update-on-page-load.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-force-update-on-page-load.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests "Force update on page load" checkbox\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); await TestRunner.loadHTML(` <p>Tests "Force update on page load" checkbox</p>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-navigation-preload.js b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-navigation-preload.js index baf9e08..967f70c 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-navigation-preload.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-navigation-preload.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests the navigation request related events are available in the DevTools\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); const scriptURL = 'http://127.0.0.1:8000/devtools/service-workers/resources/navigation-preload-worker.js';
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-redundant.js b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-redundant.js index e794085..6e3c8d0 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-redundant.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-redundant.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`ServiceWorkers must be shown correctly even if there is a redundant worker.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.loadModule('console_test_runner'); await TestRunner.showPanel('resources');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-view.js b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-view.js index e12b373..47cbabfa 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-view.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/service-workers-view.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests ServiceWorkersView on resources panel.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.loadModule('console_test_runner'); await TestRunner.showPanel('resources');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/user-agent-override.js b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/user-agent-override.js index 285536a..8abd63f9 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/user-agent-override.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/service-workers/user-agent-override.js
@@ -5,6 +5,9 @@ (async function() { TestRunner.addResult(`Tests that User-Agent override works for requests from Service Workers.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.loadModule('console_test_runner'); await TestRunner.showPanel('resources');
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/injected-script-discard-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/startup/injected-script-discard-expected.txt deleted file mode 100644 index f8584a61..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/injected-script-discard-expected.txt +++ /dev/null
@@ -1,7 +0,0 @@ -CONSOLE MESSAGE: line 1: Opening front-end for the first time -CONSOLE MESSAGE: line 1: Resolved object successfully -CONSOLE MESSAGE: line 1: Opening front-end second time -CONSOLE MESSAGE: line 1: Error resolving object -Tests that injected script is discarded upon front-end close. - -
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/injected-script-discard.html b/third_party/WebKit/LayoutTests/http/tests/devtools/startup/injected-script-discard.html deleted file mode 100644 index bf365e0..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/injected-script-discard.html +++ /dev/null
@@ -1,58 +0,0 @@ -<html> -<head> -<script src="../../inspector/inspector-test.js"></script> -<script src="../../inspector/console-test.js"></script> -<script> - -function openWebInspector() -{ - if (window.testRunner) { - testRunner.waitUntilDone(); - testRunner.showWebInspector(); - runTest(); - } -} - -function reopenWebInspector(objectId) -{ - window.objectId = unescape(objectId); - testRunner.closeWebInspector(); - setTimeout(function() { - testRunner.showWebInspector(); - runTest(); - }, 0); -} - -async function test() { - var result = await TestRunner.RuntimeAgent.evaluate('window.objectId'); - - if (result.type !== 'string') { - TestRunner.evaluateInPageAnonymously('console.log(\'Opening front-end for the first time\')'); - result = await TestRunner.RuntimeAgent.evaluate(`({ handle : "handle" })`); - checkHandleInInjectedScript(result.objectId, reopenInspector); - } else { - TestRunner.evaluateInPageAnonymously('console.log(\'Opening front-end second time\')'); - checkHandleInInjectedScript(result.value, TestRunner.completeTest); - } - - function reopenInspector() { - TestRunner.evaluateInPageAnonymously('reopenWebInspector(\'' + escape(result.objectId) + '\')'); - } - - async function checkHandleInInjectedScript(objectId, callback) { - var properties = await TestRunner.RuntimeAgent.getProperties(objectId, false); - var result = await TestRunner.evaluateInPageRemoteObject( - !properties ? 'console.log(\'Error resolving object\')' : 'console.log(\'Resolved object successfully\')'); - callback(result); - } -} - -</script> -</head> -<body onload="openWebInspector()"> -<p> -Tests that injected script is discarded upon front-end close. -</p> -<div id="container"/> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/open-close-open-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/startup/open-close-open-expected.txt deleted file mode 100644 index 3fe5d010..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/open-close-open-expected.txt +++ /dev/null
@@ -1,42 +0,0 @@ -Tests that scripts panel displays resource content correctly after the open - close - open sequence. Bug 56747 - - -Running: testSourceFrameContent -==Source frame contents start== -<html> -<head> -<script src="../../../inspector/inspector-test.js"></script> -<script src="../../../inspector/debugger-test.js"></script> -<script> - -function test() { - TestRunner.evaluateInPage('frontendReopeningCount', function(result) { - if (result._description === '0') - TestRunner.evaluateInPage('reopenFrontend()'); - else { - SourcesTestRunner.runDebuggerTestSuite([function testSourceFrameContent(next) { - SourcesTestRunner.showScriptSource('open-close-open.html', didShowScriptSource); - - function didShowScriptSource(sourceFrame) { - SourcesTestRunner.dumpSourceFrameContents(sourceFrame); - next(); - } - }]); - } - }); -} - -</script> - -</head> - -<body onload="runTest()"> -<p> -Tests that scripts panel displays resource content correctly after the open - close - open sequence. -<a href="https://bugs.webkit.org/show_bug.cgi?id=56747">Bug 56747</a> -</p> -</body> -</html> - -==Source frame contents end== -
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/open-close-open.html b/third_party/WebKit/LayoutTests/http/tests/devtools/startup/open-close-open.html deleted file mode 100644 index 6cb30c9..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/open-close-open.html +++ /dev/null
@@ -1,34 +0,0 @@ -<html> -<head> -<script src="../../../inspector/inspector-test.js"></script> -<script src="../../../inspector/debugger-test.js"></script> -<script> - -function test() { - TestRunner.evaluateInPage('frontendReopeningCount', function(result) { - if (result._description === '0') - TestRunner.evaluateInPage('reopenFrontend()'); - else { - SourcesTestRunner.runDebuggerTestSuite([function testSourceFrameContent(next) { - SourcesTestRunner.showScriptSource('open-close-open.html', didShowScriptSource); - - function didShowScriptSource(sourceFrame) { - SourcesTestRunner.dumpSourceFrameContents(sourceFrame); - next(); - } - }]); - } - }); -} - -</script> - -</head> - -<body onload="runTest()"> -<p> -Tests that scripts panel displays resource content correctly after the open - close - open sequence. -<a href="https://bugs.webkit.org/show_bug.cgi?id=56747">Bug 56747</a> -</p> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/reattach-after-editing-styles-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/startup/reattach-after-editing-styles-expected.txt deleted file mode 100644 index 60a5d1f..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/reattach-after-editing-styles-expected.txt +++ /dev/null
@@ -1,59 +0,0 @@ -This test checks that styles edited through inspector are correctly shown upon reattach. - -Opening front-end for the first time -Dump initial styles: -[expanded] -element.style { () - -[expanded] -#testDiv { (reattach-after-…-styles.html:7 -> reattach-after-editing-styles.html:7:11) - font-family: arial; - -[expanded] -#testDiv { (style.css:1 -> style.css:1:11) - color: red; - -[expanded] -div { (user agent stylesheet) - display: block; - -Dump styles after editing: -[expanded] -element.style { () - -[expanded] -#testDiv, my-custom-tag { (inspector-stylesheet:1 -> inspector-stylesheet:1:26) - -[expanded] -#testDiv { (reattach-after-…-styles.html:7 -> reattach-after-editing-styles.html:7:11) - font-family: Helvetica; - -[expanded] -#testDiv { (style.css:1 -> style.css:1:11) - color: green; - -[expanded] -div { (user agent stylesheet) - display: block; - -Opening front-end second time -Dump styles after inspector was reopened: -[expanded] -element.style { () - -[expanded] -#testDiv, my-custom-tag { (inspector-stylesheet:1 -> inspector-stylesheet:1:26) - -[expanded] -#testDiv { (reattach-after-…-styles.html:7 -> reattach-after-editing-styles.html:7:11) - font-family: Helvetica; - -[expanded] -#testDiv { (style.css:1 -> style.css:1:11) - color: green; - -[expanded] -div { (user agent stylesheet) - display: block; - -
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/reattach-after-editing-styles.html b/third_party/WebKit/LayoutTests/http/tests/devtools/startup/reattach-after-editing-styles.html deleted file mode 100644 index a785af6f..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/reattach-after-editing-styles.html +++ /dev/null
@@ -1,115 +0,0 @@ -<html> -<head> -<link rel="stylesheet" href="resources/style.css"> -<script src="../../inspector/inspector-test.js"></script> -<script src="../../inspector/elements-test.js"></script> -<style> -#testDiv { - font-family: arial; -} -</style> -<script> - -function reopenWebInspector(objectId) -{ - window.didReopen = 1; - testRunner.closeWebInspector(); - setTimeout(function() { - testRunner.showWebInspector(); - runTest(); - }, 0); -} - -function initTest() -{ - delete window.didReopen; - if (window.testRunner) - testRunner.waitUntilDone(); - if (window.testRunner) - testRunner.showWebInspector(); - runTest(); -} - -async function test() { - var result = await TestRunner.RuntimeAgent.evaluate('window.didReopen'); - - if (result.type !== 'number') { - TestRunner.addResult('Opening front-end for the first time'); - TestRunner.addResult('Dump initial styles:'); - dump(onStylesDumped); - } else { - TestRunner.addResult('Opening front-end second time'); - TestRunner.addResult('Dump styles after inspector was reopened:'); - dump(TestRunner.completeTest); - } - - function onStylesDumped() { - treeElement = ElementsTestRunner.getMatchedStylePropertyTreeItem('color'); - treeElement.startEditing(); - treeElement.nameElement.textContent = 'color'; - treeElement.nameElement.dispatchEvent(TestRunner.createKeyEvent('Enter')); - - // Commit editing. - treeElement.valueElement.textContent = 'green'; - treeElement.valueElement.firstChild.select(); - treeElement.valueElement.dispatchEvent(TestRunner.createKeyEvent('Enter')); - ElementsTestRunner.waitForStyleApplied(onStyleSheetPropertyEdited); - } - - function onStyleSheetPropertyEdited() { - treeElement = ElementsTestRunner.getMatchedStylePropertyTreeItem('font-family'); - treeElement.startEditing(); - treeElement.nameElement.textContent = 'font-family'; - treeElement.nameElement.dispatchEvent(TestRunner.createKeyEvent('Enter')); - - // Commit editing. - treeElement.valueElement.textContent = 'Helvetica'; - treeElement.valueElement.firstChild.select(); - treeElement.valueElement.dispatchEvent(TestRunner.createKeyEvent('Enter')); - ElementsTestRunner.waitForStyleApplied(onStyleTagPropertyEdited); - } - - function onStyleTagPropertyEdited() { - ElementsTestRunner.addNewRule('#testDiv, my-custom-tag', onFirstRuleAdded); - } - - function onFirstRuleAdded() { - ElementsTestRunner.addNewRule('#testDiv, another-custom-tag', onSecondRuleAdded); - } - - function onSecondRuleAdded() { - TestRunner.domModel.undo().then(onRuleRemoved); - } - - function onRuleRemoved() { - ElementsTestRunner.selectNodeAndWaitForStyles('other', step4); - } - - function step4() { - TestRunner.addResult('Dump styles after editing:'); - dump(reopenInspector); - } - - function reopenInspector() { - TestRunner.flushResults(); - TestRunner.evaluateInPage('reopenWebInspector()'); - } - - function dump(callback) { - ElementsTestRunner.selectNodeAndWaitForStyles('testDiv', step2); - - function step2() { - ElementsTestRunner.dumpSelectedElementStyles(true); - callback(); - } - } -} -</script> -</head> - -<body onload="initTest()"> -<p>This test checks that styles edited through inspector are correctly shown upon reattach.</p> -<div id="testDiv"></div> -<div id="other"></div> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/shadow-dom-rules-restart-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/startup/shadow-dom-rules-restart-expected.txt deleted file mode 100644 index 165a153..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/shadow-dom-rules-restart-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -CONSOLE MESSAGE: line 1: Opening front-end for the first time -CONSOLE MESSAGE: line 1: Opening front-end second time -This test checks that style sheets hosted inside shadow roots could be inspected if inspector is reopened. - -[expanded] -element.style { () - -[expanded] -.red { (<style>…</style>) - color: red; - -[expanded] -div { (user agent stylesheet) - display: block; - -
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/shadow-dom-rules-restart.html b/third_party/WebKit/LayoutTests/http/tests/devtools/startup/shadow-dom-rules-restart.html deleted file mode 100644 index d3a302a..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/shadow-dom-rules-restart.html +++ /dev/null
@@ -1,65 +0,0 @@ -<html> -<head> -<script src="../../inspector/inspector-test.js"></script> -<script src="../../inspector/elements-test.js"></script> -<script> - -function reopenWebInspector(objectId) -{ - window.didReopen = 1; - testRunner.closeWebInspector(); - setTimeout(function() { - testRunner.showWebInspector(); - runTest(); - }, 0); -} - -function createShadowRoot() -{ - delete window.didReopen; - if (window.testRunner) - testRunner.waitUntilDone(); - var template = document.querySelector('#tmpl'); - var root = document.querySelector('#host').createShadowRoot(); - root.appendChild(template.content.cloneNode(true)); - if (window.testRunner) - testRunner.showWebInspector(); - runTest(); -} - -async function test() { - var result = await TestRunner.RuntimeAgent.evaluate('window.didReopen'); - - if (result.type !== 'number') { - TestRunner.evaluateInPage('console.log(\'Opening front-end for the first time\')'); - runTests(reopenInspector); - } else { - TestRunner.evaluateInPage('console.log(\'Opening front-end second time\')'); - runTests(TestRunner.completeTest); - } - - function reopenInspector() { - TestRunner.evaluateInPage('reopenWebInspector()'); - } - - function runTests(callback) { - ElementsTestRunner.selectNodeAndWaitForStyles('inner', step2); - - function step2() { - ElementsTestRunner.dumpSelectedElementStyles(true); - callback(); - } - } -} -</script> -</head> - -<body onload="createShadowRoot()"> -<p>This test checks that style sheets hosted inside shadow roots could be inspected if inspector is reopened.</p> -<div id="host"></div> -<template id="tmpl"> - <style> .red { color: red; } </style> - <div id="inner" class="red">hi!</div> -</template> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/tabbed-pane-closeable-persistence-restore-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/startup/tabbed-pane-closeable-persistence-restore-expected.txt deleted file mode 100644 index e52325d..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/tabbed-pane-closeable-persistence-restore-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -Tests that persisted closeable tabs are restored. - -Has sensors tab: true -Has rendering tab: false -
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/tabbed-pane-closeable-persistence-restore.html b/third_party/WebKit/LayoutTests/http/tests/devtools/startup/tabbed-pane-closeable-persistence-restore.html deleted file mode 100644 index 625bef7f..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/startup/tabbed-pane-closeable-persistence-restore.html +++ /dev/null
@@ -1,25 +0,0 @@ -<html> -<head> -<script src="../../inspector/inspector-test.js"></script> -<script> - -function onload() -{ - testRunner.showWebInspector(JSON.stringify({ "drawer-view-closeableTabs": JSON.stringify({ sensors: true }) })); - runTest(); -} - -function test() { - var drawer = UI.inspectorView._drawerTabbedLocation.tabbedPane(); - TestRunner.addResult('Has sensors tab: ' + drawer.hasTab('sensors')); - TestRunner.addResult('Has rendering tab: ' + drawer.hasTab('rendering')); - TestRunner.completeTest(); -} - -</script> -</head> - -<body onload="onload()"> -<p>Tests that persisted closeable tabs are restored.</p> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/storage-panel-dom-storage-update.js b/third_party/WebKit/LayoutTests/http/tests/devtools/storage-panel-dom-storage-update.js index 81ab357..1bea5b6 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/storage-panel-dom-storage-update.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/storage-panel-dom-storage-update.js
@@ -6,6 +6,9 @@ TestRunner.addResult( `Test that storage panel is present and that it contains correct data whenever localStorage is updated.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); await TestRunner.evaluateInPagePromise(` function addItem(key, value)
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/storage-panel-dom-storage.js b/third_party/WebKit/LayoutTests/http/tests/devtools/storage-panel-dom-storage.js index f24eab83..4a6a341d 100644 --- a/third_party/WebKit/LayoutTests/http/tests/devtools/storage-panel-dom-storage.js +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/storage-panel-dom-storage.js
@@ -6,6 +6,9 @@ TestRunner.addResult( `Test that storage panel is present and that it contains correct data for local and session DOM storages.\n`); await TestRunner.loadModule('application_test_runner'); + // Note: every test that uses a storage API must manually clean-up state from previous tests. + await ApplicationTestRunner.resetState(); + await TestRunner.showPanel('resources'); await TestRunner.evaluateInPagePromise(` function populateDOMStorage()
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/target/resume-on-close-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/target/resume-on-close-expected.txt new file mode 100644 index 0000000..b36c6455 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/target/resume-on-close-expected.txt
@@ -0,0 +1,8 @@ +Tests that closing the page will resume the render process. +Opened a second window +Attached to a second window +Paused in a second window +Closed a second window +Received window destroyed notification +setTimeout worked in first window +
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/target/resume-on-close.js b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/target/resume-on-close.js new file mode 100644 index 0000000..b0a11caf --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/inspector-protocol/target/resume-on-close.js
@@ -0,0 +1,42 @@ +(async function(testRunner) { + var {page, session, dp} = await testRunner.startBlank( + `Tests that closing the page will resume the render process.`); + + await dp.Target.setDiscoverTargets({discover: true}); + session.evaluate(` + window.myWindow = window.open('../resources/inspector-protocol-page.html'); undefined; + `); + testRunner.log('Opened a second window'); + + var event = await dp.Target.onceTargetInfoChanged(event => event.params.targetInfo.url.endsWith('inspector-protocol-page.html')); + var targetId = event.params.targetInfo.targetId; + + var sessionId = (await dp.Target.attachToTarget({targetId: targetId})).result.sessionId; + testRunner.log('Attached to a second window'); + await dp.Target.sendMessageToTarget({ + sessionId: sessionId, + message: JSON.stringify({id: 1, method: 'Debugger.enable'}) + }); + dp.Target.sendMessageToTarget({ + sessionId: sessionId, + message: JSON.stringify({id: 2, method: 'Runtime.evaluate', params: {expression: 'debugger;'}}) + }); + await dp.Target.onceReceivedMessageFromTarget(event => { + var message = JSON.parse(event.params.message); + return message.method === 'Debugger.paused'; + }); + testRunner.log('Paused in a second window'); + + session.evaluate(` + window.myWindow.close(); undefined; + `); + testRunner.log('Closed a second window'); + await dp.Target.onceTargetDestroyed(event => event.params.targetId === targetId); + testRunner.log('Received window destroyed notification'); + + await session.evaluateAsync(` + new Promise(f => setTimeout(f, 0)) + `); + testRunner.log('setTimeout worked in first window'); + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/OWNERS b/third_party/WebKit/LayoutTests/http/tests/inspector/OWNERS deleted file mode 100644 index 0e56faf..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -# TEAM: devtools-dev@chromium.org
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/appcache/appcache-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/appcache/appcache-test.js deleted file mode 100644 index f619bb1..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/appcache/appcache-test.js +++ /dev/null
@@ -1,3 +0,0 @@ -var initialize_ApplicationCacheTest = function() { - InspectorTest.preloadModule("application_test_runner"); -};
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/bindings/bindings-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/bindings/bindings-test.js deleted file mode 100644 index f69e1a0..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/bindings/bindings-test.js +++ /dev/null
@@ -1,4 +0,0 @@ -var initialize_BindingsTest = function() { - InspectorTest.preloadModule("bindings_test_runner"); - InspectorTest.preloadModule("sources"); -}
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/cache-storage/cache-storage-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/cache-storage/cache-storage-test.js deleted file mode 100644 index c848fe7..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/cache-storage/cache-storage-test.js +++ /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. - -var initialize_CacheStorageTest = function() { - InspectorTest.preloadModule("application_test_runner"); - InspectorTest.preloadPanel("resources"); -}
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/console-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/console-test.js deleted file mode 100644 index d3e53114..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/console-test.js +++ /dev/null
@@ -1,7 +0,0 @@ -var initialize_ConsoleTest = function() { - -InspectorTest.preloadModule("console_test_runner"); -InspectorTest.preloadModule("source_frame"); -InspectorTest.preloadPanel("console"); - -}
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js deleted file mode 100644 index aafdeab..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/debugger-test.js +++ /dev/null
@@ -1,5 +0,0 @@ -var initialize_DebuggerTest = function() { - InspectorTest.preloadModule('sources_test_runner'); - - InspectorTest.preloadPanel("sources"); -};
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js deleted file mode 100644 index f12a78f..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/elements-test.js +++ /dev/null
@@ -1,4 +0,0 @@ -var initialize_ElementTest = function() { - InspectorTest.preloadModule('elements_test_runner'); - InspectorTest.preloadPanel("elements"); -};
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/extensions-network-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions-network-test.js deleted file mode 100644 index 44b66a99..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/extensions-network-test.js +++ /dev/null
@@ -1,18 +0,0 @@ -function extension_getRequestByUrl(urls, callback) -{ - function onHAR(response) - { - var entries = response.entries; - for (var i = 0; i < entries.length; ++i) { - for (var url = 0; url < urls.length; ++url) { - if (urls[url].test(entries[i].request.url)) { - callback(entries[i]); - return; - } - } - } - output("no item found"); - callback(null); - } - webInspector.network.getHAR(onHAR); -}
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/extensions-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions-test.js deleted file mode 100644 index 51e0ce8..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/extensions-test.js +++ /dev/null
@@ -1,30 +0,0 @@ -var initialize_ExtensionsTest = function() -{ - InspectorTest.preloadModule('extensions_test_runner'); -} - -// TODO(chenwilliam): these should be in ExtensionsTestRunner.js initAsync(...) -// however these are here because they need to be executed when the inspected page reloads -function extensionFunctions() -{ - var functions = ""; - - for (symbol in window) { - if (/^extension_/.exec(symbol) && typeof window[symbol] === "function") - functions += window[symbol].toString(); - } - return functions; -} - -var extensionsOrigin = "http://devtools-extensions.oopif.test:8000"; - -function extension_showPanel(panelId, callback) -{ - evaluateOnFrontend("InspectorTest.showPanel(unescape('" + escape(panelId) + "')).then(function() { reply(); });", callback); -} - -var test = function() -{ - Common.moduleSetting("shortcutPanelSwitch").set(true); - ExtensionsTestRunner.runExtensionTests(); -}
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/indexeddb-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/indexeddb-test.js deleted file mode 100644 index 879a093..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/indexeddb-test.js +++ /dev/null
@@ -1,4 +0,0 @@ -var initialize_IndexedDBTest = function() { - InspectorTest.preloadModule("application_test_runner"); - InspectorTest.preloadPanel("resources"); -}
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js deleted file mode 100644 index 322aea3f..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/inspector-test.js +++ /dev/null
@@ -1,400 +0,0 @@ -/** - * These test helper APIs are being migrated to - * third_party/WebKit/Source/devtools/front_end/test_runner - * See crbug.com/667560 - */ - -if (window.GCController) - GCController.collectAll(); - -var initialize_InspectorTest = function() { -Protocol.InspectorBackend.Options.suppressRequestErrors = true; -var results = []; - -function consoleOutputHook(messageType) -{ - InspectorTest.addResult(messageType + ": " + Array.prototype.slice.call(arguments, 1)); -} - -window._originalConsoleLog = console.log.bind(console); - -console.log = consoleOutputHook.bind(InspectorTest, "log"); -console.error = consoleOutputHook.bind(InspectorTest, "error"); -console.info = consoleOutputHook.bind(InspectorTest, "info"); -console.assert = function(condition, object) -{ - if (condition) - return; - var message = "Assertion failed: " + (typeof object !== "undefined" ? object : ""); - InspectorTest.addResult(new Error(message).stack); -} - -InspectorTest.completeTest = function() -{ - InspectorTest.RuntimeAgent.evaluate("completeTest(\"" + escape(JSON.stringify(results)) + "\")", "test"); -} - -InspectorTest.flushResults = function() -{ - InspectorTest.RuntimeAgent.evaluate("flushResults(\"" + escape(JSON.stringify(results)) + "\")", "test"); - results = []; -} - -/** - * TestRunner.evaluateInPage inserts sourceURL by inspecting the call stack. - */ -InspectorTest.evaluateInPage = async function(code, callback) -{ - var response = await InspectorTest.RuntimeAgent.invoke_evaluate({ - expression: code, - objectGroup: "console" - }); - if (!response[Protocol.Error]) - InspectorTest.safeWrap(callback)(response.result.value, response.exceptionDetails); -} - -/** - * TestRunner.evaluateInPageRemoteObject inserts sourceURL by inspecting the call stack. - */ -InspectorTest.evaluateInPageRemoteObject = async function(code, callback) -{ - var response = await InspectorTest.RuntimeAgent.invoke_evaluate({ - expression: code, - objectGroup: "console" - }); - if (!response[Protocol.Error]) - return InspectorTest.runtimeModel.createRemoteObject(response.result); -} - -InspectorTest.addResult = function(text) -{ - results.push(String(text)); -} - -window.onerror = function (message, filename, lineno, colno, error) -{ - InspectorTest.addResult("Uncaught exception in inspector front-end: " + message + " [" + error.stack + "]"); - InspectorTest.completeTest(); -} - -InspectorTest.navigate = function(url, callback) -{ - InspectorTest._pageLoadedCallback = InspectorTest.safeWrap(callback); - InspectorTest.evaluateInPage("window.location.replace('" + url + "')"); -} - -InspectorTest.navigatePromise = function(url) -{ - var fulfill; - var promise = new Promise(callback => fulfill = callback); - InspectorTest.navigate(url, fulfill); - return promise; -} - -InspectorTest.hardReloadPage = function(callback, scriptToEvaluateOnLoad) -{ - InspectorTest._innerReloadPage(true, callback, scriptToEvaluateOnLoad); -} - -InspectorTest.reloadPage = function(callback, scriptToEvaluateOnLoad) -{ - InspectorTest._innerReloadPage(false, callback, scriptToEvaluateOnLoad); -} - -InspectorTest.reloadPagePromise = function(scriptToEvaluateOnLoad) -{ - var fulfill; - var promise = new Promise(x => fulfill = x); - InspectorTest.reloadPage(fulfill, scriptToEvaluateOnLoad); - return promise; -} - -InspectorTest._innerReloadPage = function(hardReload, callback, scriptToEvaluateOnLoad) -{ - InspectorTest._pageLoadedCallback = InspectorTest.safeWrap(callback); - - if (UI.panels.network) - NetworkLog.networkLog.reset(); - InspectorTest.resourceTreeModel.reloadPage(hardReload, scriptToEvaluateOnLoad); -} - -InspectorTest.pageLoaded = function() -{ - InspectorTest.addResult("Page reloaded."); - if (InspectorTest._pageLoadedCallback) { - var callback = InspectorTest._pageLoadedCallback; - delete InspectorTest._pageLoadedCallback; - callback(); - } -} - -InspectorTest.runWhenPageLoads = function(callback) -{ - var oldCallback = InspectorTest._pageLoadedCallback; - function chainedCallback() - { - if (oldCallback) - oldCallback(); - callback(); - } - InspectorTest._pageLoadedCallback = InspectorTest.safeWrap(chainedCallback); -} - -InspectorTest.addConsoleSniffer = function(override, opt_sticky) -{ - InspectorTest.addSniffer(ConsoleModel.ConsoleModel.prototype, "addMessage", override, opt_sticky); -} - -SDK.targetManager.observeTargets({ - targetAdded: function(target) - { - if (TestRunner.CSSAgent) - return; - TestRunner._setupTestHelpers(target); - InspectorTest.consoleModel = ConsoleModel.consoleModel; - InspectorTest.networkLog = NetworkLog.networkLog; - InspectorTest = Object.assign({}, self.TestRunner, InspectorTest); - }, - - targetRemoved: function(target) { } -}); - -InspectorTest._panelsToPreload = []; - -InspectorTest.preloadPanel = function(panelName) -{ - InspectorTest._panelsToPreload.push(panelName); -} - -InspectorTest._modulesToPreload = []; - -InspectorTest.preloadModule = function(moduleName) -{ - InspectorTest._modulesToPreload.push(moduleName); -} - -self.AccessibilityTestRunner = InspectorTest; -self.ApplicationTestRunner = InspectorTest; -self.AuditsTestRunner = InspectorTest; -self.BindingsTestRunner = InspectorTest; -self.ConsoleTestRunner = InspectorTest; -self.CoverageTestRunner = InspectorTest; -self.DataGridTestRunner = InspectorTest; -self.DeviceModeTestRunner = InspectorTest; -self.ElementsTestRunner = InspectorTest; -self.ExtensionsTestRunner = InspectorTest; -self.LayersTestRunner = InspectorTest; -self.NetworkTestRunner = InspectorTest; -self.PerformanceTestRunner = InspectorTest; -self.ProfilerTestRunner = InspectorTest; -self.SASSTestRunner = InspectorTest; -self.SecurityTestRunner = InspectorTest; -self.SDKTestRunner = InspectorTest; -self.SourcesTestRunner = InspectorTest; -self.TestRunner = Object.assign(self.TestRunner, InspectorTest); - - }; // initialize_InspectorTest - -var initializeCallId = 0; -var runTestCallId = 1; -var evalCallbackCallId = 2; -var frontendReopeningCount = 0; - -function reopenFrontend() -{ - closeFrontend(openFrontendAndIncrement); -} - -function closeFrontend(callback) -{ - // Do this asynchronously to allow InspectorBackendDispatcher to send response - // back to the frontend before it's destroyed. - // FIXME: we need a better way of waiting for chromium events to happen - setTimeout(function() { - testRunner.closeWebInspector(); - callback(); - }, 1); -} - -function openFrontendAndIncrement() -{ - frontendReopeningCount++; - testRunner.showWebInspector(JSON.stringify({testPath: '"' + location.href + '"'}).replace(/\"/g,"%22")); - setTimeout(runTest, 1); -} - -function runAfterIframeIsLoaded() -{ - if (window.testRunner) - testRunner.waitUntilDone(); - function step() - { - if (!window.iframeLoaded) - setTimeout(step, 100); - else - runTest(); - } - setTimeout(step, 100); -} - -function runTest(pixelTest) -{ - if (!window.testRunner) - return; - - if (pixelTest) - testRunner.dumpAsTextWithPixelResults(); - else - testRunner.dumpAsText(); - testRunner.waitUntilDone(); - - function initializeFrontend(initializationFunctions) - { - if (window.InspectorTest) { - InspectorTest.pageLoaded(); - return; - } - - InspectorTest = {}; - - for (var i = 0; i < initializationFunctions.length; ++i) { - try { - initializationFunctions[i](); - } catch (e) { - console.error("Exception in test initialization: " + e + " " + e.stack); - InspectorTest.completeTest(); - } - } - } - - function runTestInFrontend(testFunction) - { - if (InspectorTest.wasAlreadyExecuted) - return; - - InspectorTest.wasAlreadyExecuted = true; - - // 1. Preload panels. - var lastLoadedPanel; - - var promise = Promise.resolve(); - - for (let moduleName of InspectorTest._modulesToPreload) - promise = promise.then(() => TestRunner.loadModule(moduleName)); - - for (var i = 0; i < InspectorTest._panelsToPreload.length; ++i) { - let panel = InspectorTest._panelsToPreload[i]; - lastLoadedPanel = panel; - promise = promise.then(() => UI.inspectorView.panel(panel)); - } - - var testPath = Common.settings.createSetting("testPath", "").get(); - - // 2. Show initial panel based on test path. - var initialPanelByFolder = { - "animation": "elements", - "audits": "audits", - "console": "console", - "elements": "elements", - "editor": "sources", - "layers": "layers", - "network": "network", - "profiler": "heap_profiler", - "resource-tree": "resources", - "search": "sources", - "service-workers": "resources", - "sources": "sources", - "timeline": "timeline", - "tracing": "timeline", - } - var initialPanelShown = false; - for (var folder in initialPanelByFolder) { - if (testPath.indexOf(folder + "/") !== -1) { - lastLoadedPanel = initialPanelByFolder[folder]; - promise = promise.then(() => UI.inspectorView.panel(lastLoadedPanel)); - break; - } - } - - // 3. Run test function. - promise.then(() => { - if (lastLoadedPanel) - UI.inspectorView.showPanel(lastLoadedPanel).then(testFunction); - else - testFunction(); - }).catch(function(e) { - console.error(e); - InspectorTest.completeTest(); - }); - } - - var initializationFunctions = [ String(initialize_InspectorTest) ]; - for (var name in window) { - if (name.indexOf("initialize_") === 0 && typeof window[name] === "function" && name !== "initialize_InspectorTest") - initializationFunctions.push(window[name].toString()); - } - var toEvaluate = "(" + initializeFrontend + ")(" + "[" + initializationFunctions + "]" + ");"; - testRunner.evaluateInWebInspector(initializeCallId, toEvaluate); - - if (window.debugTest) - test = "function() { Protocol.InspectorBackend.Options.suppressRequestErrors = false; window.test = " + test.toString() + "; InspectorTest.addResult = window._originalConsoleLog; InspectorTest.completeTest = () => console.log('Test completed'); TestRunner.addResult = InspectorTest.addResult; TestRunner.completeTest = InspectorTest.completeTest; }"; - toEvaluate = "(" + runTestInFrontend + ")(" + test + ");"; - testRunner.evaluateInWebInspector(runTestCallId, toEvaluate); -} - -function runTestAfterDisplay() -{ - if (!window.testRunner) - return; - - testRunner.waitUntilDone(); - requestAnimationFrame(() => runTest()); -} - -function completeTest(results) -{ - flushResults(results); - closeInspectorAndNotifyDone(); -} - -function flushResults(results) -{ - results = (JSON && JSON.parse ? JSON.parse : eval)(unescape(results)); - for (var i = 0; i < results.length; ++i) - _output(results[i]); -} - -function closeInspectorAndNotifyDone() -{ - testRunner.closeWebInspector(); - setTimeout(function() { - testRunner.notifyDone(); - }, 0); -} - -var outputElement; - -function createOutputElement() -{ - outputElement = document.createElement("div"); - // Support for svg - add to document, not body, check for style. - if (outputElement.style) { - outputElement.style.whiteSpace = "pre"; - outputElement.style.height = "10px"; - outputElement.style.overflow = "hidden"; - } - document.documentElement.appendChild(outputElement); -} - -function output(text) -{ - _output("[page] " + text); -} - -function _output(result) -{ - if (!outputElement) - createOutputElement(); - outputElement.appendChild(document.createTextNode(result)); - outputElement.appendChild(document.createElement("br")); -}
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/isolated-filesystem-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/isolated-filesystem-test.js deleted file mode 100644 index 1852314..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/isolated-filesystem-test.js +++ /dev/null
@@ -1,3 +0,0 @@ -var initialize_IsolatedFileSystemTest = function() { - InspectorTest.preloadModule('bindings_test_runner'); -};
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/layers-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/layers-test.js deleted file mode 100644 index 12f07a6..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/layers-test.js +++ /dev/null
@@ -1,3 +0,0 @@ -function initialize_LayerTreeTests() { - InspectorTest.preloadModule('layers_test_runner'); -}
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/live-edit-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/live-edit-test.js deleted file mode 100644 index 2c64fc0..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/live-edit-test.js +++ /dev/null
@@ -1,3 +0,0 @@ -var initialize_LiveEditTest = function() { - InspectorTest.preloadModule('sources_test_runner'); -};
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/network-test.js deleted file mode 100644 index 1a19397a..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/network-test.js +++ /dev/null
@@ -1,4 +0,0 @@ -var initialize_NetworkTest = function() { - InspectorTest.preloadModule("network_test_runner"); - InspectorTest.preloadPanel("network"); -};
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/cors-redirect.cgi b/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/cors-redirect.cgi deleted file mode 100755 index 6441e31..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/cors-redirect.cgi +++ /dev/null
@@ -1,14 +0,0 @@ -#!/usr/bin/perl -wT -use strict; -use CGI; -my $q = CGI->new; -my %headers = map { $_ => $q->http($_) } $q->http(); - -print "Status: 307 Internal Redirect\n"; -print "Location: cors.cgi\n"; -print "Access-Control-Allow-Headers:X-PINGARUNER, CONTENT-TYPE, X-TEST\n"; -print "Access-Control-Allow-Methods:POST, GET, OPTIONS\n"; -print "Access-Control-Allow-Origin:http://127.0.0.1:8000\n"; -print "Access-Control-Max-Age:1728000\n"; -print "\n"; -print "OK";
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/cors.cgi b/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/cors.cgi deleted file mode 100755 index 4e99fc1..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/cors.cgi +++ /dev/null
@@ -1,10 +0,0 @@ -#!/usr/bin/perl -wT -use strict; - -print "Status: 200 OK\n"; -print "Access-Control-Allow-Headers:X-PINGARUNER, CONTENT-TYPE\n"; -print "Access-Control-Allow-Methods:POST, GET, OPTIONS\n"; -print "Access-Control-Allow-Origin:http://127.0.0.1:8000\n"; -print "Access-Control-Max-Age:1728000\n"; -print "\n"; -print "OK";
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/print-cookie.php b/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/print-cookie.php deleted file mode 100644 index 1565dfd..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/print-cookie.php +++ /dev/null
@@ -1,9 +0,0 @@ -<?php - header("Expires: Thu, 01 Dec 2003 16:00:00 GMT"); - header("Cache-Control: no-store, no-cache, must-revalidate"); - header("Pragma: no-cache"); - header("Content-Type: text/plain"); - setcookie("TestCookie", "TestCookieValue"); - - echo("Cookie value: " . $_COOKIE["TestCookie"] . "."); -?>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/resource.php b/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/resource.php deleted file mode 100644 index c2b6f1ccc..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/resource.php +++ /dev/null
@@ -1,119 +0,0 @@ -<?php - $type = $_GET["type"]; - $wait = $_GET["wait"]; - $send = $_GET["send"]; - $size = $_GET["size"]; - $gzip = $_GET["gzip"]; - $jsdelay = $_GET["jsdelay"]; - $jscontent = $_GET["jscontent"]; - $chunked = $_GET["chunked"]; - $random = $_GET["random"]; - $cached = $_GET["cached"]; - - # Wait before sending response - if ($wait) - usleep($wait * 1000); - - # Exit early if we return 304 code. - if ($cached && $_SERVER["HTTP_IF_MODIFIED_SINCE"]) { - header("HTTP/1.0 304 Not Modified"); - exit; - } - - # Enable gzip compression if needed - if ($gzip) - ob_start("ob_gzhandler"); - - # Send headers - if ($cached) { - $max_age = 12 * 31 * 24 * 60 * 60; //one year - $expires = gmdate(DATE_RFC1123, time() + $max_age); - $last_modified = gmdate(DATE_RFC1123, time() - $max_age); - - header("Cache-Control: public, max-age=" . 5*$max_age); - header("Cache-control: max-age=0"); - header("Expires: " . $expires); - header("Last-Modified: " . $last_modified); - } else { - header("Expires: Thu, 01 Dec 2003 16:00:00 GMT"); - header("Cache-Control: no-store, no-cache, must-revalidate"); - header("Pragma: no-cache"); - } - if ($type == "js") - header("Content-Type:text/javascript; charset=UTF-8"); - else if ($type == "image") - header("Content-Type: image/png"); - else - header("Content-Type: text/plain"); - - # Flush headers and sleep bofore sending response - if ($send) { - flush(); - usleep($send * 1000); - } - - if ($type == "js") { - # Send JavaScript file - $bytes_emitted = 0; - if ($jsdelay) { - # JavaScript file should block on load -?> -function __foo(seconds) { - var now = Date.now(); - var counter = Number(0); - while(now + seconds > Date.now()) { counter = Number(counter + 1); } -} -__foo(<?php echo($jsdelay)?>); -<?php - $bytes_emitted += 175; - } - - if (!$jscontent) - $jscontent = "function foo() {}"; - - # JavaScript file should issue given command. - echo($jscontent); - $bytes_emitted += strlen($jscontent); - - if ($size) { - for ($i = 0; $i < $size - $bytes_emitted; ++$i) - echo("/"); - } - } else if ($type == "image") { - $base64data = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAYCAYAAACbU/80AAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9kICQsw" . - "ARCJCogAAABFSURBVEjH7ZLBCQAwCAONdP+V0xVqq0gx9w+Gi2ZCTAcXGWbe8G4Dq9DekS" . - "kPaGeFgfYJVODlCTnWADILoEg3vplACLEBN9UGG9+mxboAAAAASUVORK5CYII="; - $data = base64_decode($base64data); - $data_len = strlen($data); - print($data); - if ($size) { - if ($chunked) { - ob_flush(); - flush(); - } - for ($i = 0; $size && $i < $size - $data_len; ++$i) - echo("="); - } else if ($random) - echo(rand()); - } else { - # Generate dummy text/html. - if ($size) { - for ($i = 0; $i < $size; ++$i) { - if ($chunked && (1 == $i)) { - ob_flush(); - flush(); - } - echo("*"); - } - } else { - echo("Hello "); - if ($chunked) { - ob_flush(); - flush(); - } - echo("world"); - if ($random) - echo(": " . rand()); - } - } -?>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/set-cookie.php b/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/set-cookie.php deleted file mode 100644 index f4b87010..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/network/resources/set-cookie.php +++ /dev/null
@@ -1,18 +0,0 @@ -<?php - header("Expires: Thu, 01 Dec 2003 16:00:00 GMT"); - header("Cache-Control: no-store, no-cache, must-revalidate"); - header("Pragma: no-cache"); - header("Content-Type: text/plain"); - header("Access-Control-Allow-Origin: http://127.0.0.1:8000"); - $length = isset($_GET["length"]) ? (int) $_GET["length"] : 0; - if (!$length) { - setcookie("TestCookie", "TestCookieValue"); - } else { - $data = ""; - for ($i = 0; $i < $length; $i++) { - $data .= "a"; - } - header("Set-Cookie: $data"); - } - echo("Cookie set."); -?>
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/page-mock.js b/third_party/WebKit/LayoutTests/http/tests/inspector/page-mock.js deleted file mode 100644 index 51a57153..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/page-mock.js +++ /dev/null
@@ -1,3 +0,0 @@ -var initialize_EmptyPageMock = function() { - InspectorTest.preloadModule("sdk_test_runner"); -}; \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/automapping-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/automapping-test.js deleted file mode 100644 index 794df0b1..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/automapping-test.js +++ /dev/null
@@ -1,3 +0,0 @@ -var initialize_AutomappingTest = function() { - InspectorTest.preloadModule('bindings_test_runner'); -}
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/persistence-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/persistence-test.js deleted file mode 100644 index 7095bd7..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/persistence/persistence-test.js +++ /dev/null
@@ -1,4 +0,0 @@ -var initialize_PersistenceTest = function() { - InspectorTest.preloadModule('bindings_test_runner'); - InspectorTest.preloadModule("sources"); -}
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/product-registry-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/product-registry-test.js deleted file mode 100644 index 2db7b48..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/product-registry-test.js +++ /dev/null
@@ -1,3 +0,0 @@ -var initialize_ProductRegistry = function() { - InspectorTest.preloadModule("network_test_runner"); -};
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/resource-tree/resource-tree-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/resource-tree/resource-tree-test.js deleted file mode 100644 index f128826..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/resource-tree/resource-tree-test.js +++ /dev/null
@@ -1,3 +0,0 @@ -var initialize_ResourceTreeTest = function() { - InspectorTest.preloadModule('application_test_runner'); -};
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/resources-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/resources-test.js deleted file mode 100644 index 2a100bc..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/resources-test.js +++ /dev/null
@@ -1,5 +0,0 @@ -var initialize_ResourceTest = function() { - InspectorTest.preloadModule("application_test_runner"); - InspectorTest.preloadPanel("sources"); - InspectorTest.preloadPanel("resources"); -}
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/search/search-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/search/search-test.js deleted file mode 100644 index e388312..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/search/search-test.js +++ /dev/null
@@ -1,3 +0,0 @@ -var initialize_SearchTest = function() { - InspectorTest.preloadModule('sources_test_runner'); -};
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/security-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/security-test.js deleted file mode 100644 index 79f1683..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/security-test.js +++ /dev/null
@@ -1,4 +0,0 @@ -var initialize_SecurityTest = function() { - InspectorTest.preloadModule("security_test_runner"); - InspectorTest.preloadPanel("security"); -}
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 deleted file mode 100644 index 651a621..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/service-workers/service-workers-test.js +++ /dev/null
@@ -1,3 +0,0 @@ -var initialize_ServiceWorkersTest = function() { - InspectorTest.preloadModule('application_test_runner'); -}
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/sources-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/sources-test.js deleted file mode 100644 index 723c1f7..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/sources-test.js +++ /dev/null
@@ -1,4 +0,0 @@ -var initialize_SourcesTest = function() { - InspectorTest.preloadModule('sources_test_runner'); - InspectorTest.preloadPanel("sources"); -};
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/timeline-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/timeline-test.js deleted file mode 100644 index 9ff2c0e..0000000 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/timeline-test.js +++ /dev/null
@@ -1,4 +0,0 @@ -var initialize_Timeline = function() { - InspectorTest.preloadModule("performance_test_runner"); - InspectorTest.preloadPanel("timeline"); -};
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 7b15c4f..1abbec73 100644 --- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -134,6 +134,14 @@ getter reason getter wasClean method constructor +interface CookieStore + attribute @@toStringTag + method constructor + method delete + method get + method getAll + method has + method set interface CountQueuingStrategy method constructor method size @@ -2574,6 +2582,7 @@ attribute console attribute internals getter clients + getter cookieStore getter onabortpayment getter onactivate getter onbackgroundfetchabort @@ -2593,6 +2602,7 @@ method fetch method gc method skipWaiting + setter cookieStore setter onabortpayment setter onactivate setter onbackgroundfetchabort
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/css/reattach-after-editing-styles-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/css/reattach-after-editing-styles-expected.txt new file mode 100644 index 0000000..36d7e1eb --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/css/reattach-after-editing-styles-expected.txt
@@ -0,0 +1,44 @@ +This test checks that styles edited through inspector are correctly shown upon reattach. + +==== Original: Matching rules for #test ==== +Dumping matched rules: +*#test* { regular + background-color: blue; +} +Dumping inherited rules: + +CSS.setStyleTexts(...) to existing stylesheet +==== Style sheet text ==== +#test { + content: 'EDITED'; +} + +CSS.addRule(...) to new stylesheet +==== Style sheet text ==== +#inspected, #test { height: 1 } + + +==== Modified: Matching rules for #test ==== +Dumping matched rules: +*#test* { regular + content: 'EDITED'; +} +#inspected, *#test* { inspector + height: 1; +} +Dumping inherited rules: + +Disconnecting devtools + +Reattaching devtools + +==== Reattached: Matching rules for #test ==== +Dumping matched rules: +*#test* { regular + content: 'EDITED'; +} +#inspected, *#test* { inspector + height: 1; +} +Dumping inherited rules: +
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/css/reattach-after-editing-styles.js b/third_party/WebKit/LayoutTests/inspector-protocol/css/reattach-after-editing-styles.js new file mode 100644 index 0000000..64f57789 --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/css/reattach-after-editing-styles.js
@@ -0,0 +1,58 @@ +(async function(testRunner) { + var {page, session, dp} = await testRunner.startHTML(` +<link rel='stylesheet' href='${testRunner.url('resources/reattach-after-editing-styles.css')}'/> +<div id='test'></div> +`, 'This test checks that styles edited through inspector are correctly shown upon reattach.'); + + var CSSHelper = await testRunner.loadScript('../resources/css-helper.js'); + var cssHelper = new CSSHelper(testRunner, dp); + + dp.DOM.enable(); + dp.CSS.enable(); + await dp.Page.enable() + + var event = await dp.CSS.onceStyleSheetAdded(); + var originalStylesheetId = event.params.header.styleSheetId; + var documentNodeId = await cssHelper.requestDocumentNodeId(); + + var response = await dp.Page.getResourceTree(); + var frameId = response.result.frameTree.frame.id; + + var setStyleTexts = cssHelper.setStyleTexts.bind(cssHelper, originalStylesheetId, false); + + testRunner.log('\n==== Original: Matching rules for #test ===='); + await cssHelper.loadAndDumpMatchingRules(documentNodeId, '#test'); + + testRunner.log('\nCSS.setStyleTexts(...) to existing stylesheet'); + await setStyleTexts([{ + styleSheetId: originalStylesheetId, + range: { startLine: 0, startColumn: 7, endLine: 2, endColumn: 0 }, + text: "\n content: 'EDITED';\n", + }]); + + testRunner.log('\nCSS.addRule(...) to new stylesheet'); + var response = await dp.CSS.createStyleSheet({frameId: frameId}); + var newStylesheetId = response.result.styleSheetId; + await cssHelper.addRule(newStylesheetId, false, { + location: { startLine: 0, startColumn: 0, endLine: 0, endColumn: 0 }, + ruleText: '#inspected, #test { height: 1 }\n', + }); + + testRunner.log('\n==== Modified: Matching rules for #test ===='); + await cssHelper.loadAndDumpMatchingRules(documentNodeId, '#test'); + + testRunner.log('\nDisconnecting devtools'); + await session.disconnect(); + + testRunner.log('\nReattaching devtools'); + session = await page.createSession(); + var dp = session.protocol; + var cssHelper = new CSSHelper(testRunner, dp); + dp.DOM.enable(); + dp.CSS.enable(); + var documentNodeId = await cssHelper.requestDocumentNodeId(); + + testRunner.log('\n==== Reattached: Matching rules for #test ===='); + await cssHelper.loadAndDumpMatchingRules(documentNodeId, '#test'); + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/css/resources/reattach-after-editing-styles.css b/third_party/WebKit/LayoutTests/inspector-protocol/css/resources/reattach-after-editing-styles.css new file mode 100644 index 0000000..be37a8f --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/css/resources/reattach-after-editing-styles.css
@@ -0,0 +1,3 @@ +#test { + background-color: blue; +} \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/css/shadow-dom-rules-restart-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/css/shadow-dom-rules-restart-expected.txt new file mode 100644 index 0000000..49d3e7a --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/css/shadow-dom-rules-restart-expected.txt
@@ -0,0 +1,14 @@ +Test that style sheets hosted inside shadow roots could be inspected if inspector is reopened. + +DevTools session #1: + +Disconnecting devtools. + +DevTools session #2: +Dumping #inner node styles in shadow root: +Dumping matched rules: +*.red* { regular + color: red; +} +Dumping inherited rules: +
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/css/shadow-dom-rules-restart.js b/third_party/WebKit/LayoutTests/inspector-protocol/css/shadow-dom-rules-restart.js new file mode 100644 index 0000000..3d8a4bd --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/css/shadow-dom-rules-restart.js
@@ -0,0 +1,36 @@ +(async function(testRunner) { + var {page, session} = await testRunner.startHTML(` + <div id="host"></div> + <template id="tmpl"> + <style> .red { color: red; } </style> + <div id="inner" class="red">hi!</div> + </template> +`, 'Test that style sheets hosted inside shadow roots could be inspected if inspector is reopened.'); + + testRunner.log('\nDevTools session #1:'); + session.evaluate(` + var template = document.querySelector('#tmpl'); + var root = document.querySelector('#host').createShadowRoot(); + root.appendChild(template.content.cloneNode(true)); + `); + + testRunner.log('\nDisconnecting devtools.'); + await session.disconnect(); + + testRunner.log('\nDevTools session #2:'); + session = await page.createSession(); + var dp = session.protocol; + + await dp.DOM.enable(); + await dp.CSS.enable(); + + var CSSHelper = await testRunner.loadScript('../resources/css-helper.js'); + var cssHelper = new CSSHelper(testRunner, dp); + + testRunner.log('Dumping #inner node styles in shadow root:'); + var {result} = await dp.DOM.getFlattenedDocument({pierce: true}); + var shadowRoot = result.nodes.filter(node => node.shadowRoots)[0].shadowRoots[0]; + var nodeId = await cssHelper.requestNodeId(shadowRoot.nodeId, '#inner'); + await cssHelper.loadAndDumpMatchingRulesForNode(nodeId); + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/injected-script-discard-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/injected-script-discard-expected.txt new file mode 100644 index 0000000..c20f06e --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/injected-script-discard-expected.txt
@@ -0,0 +1,12 @@ +Tests that injected script is discarded upon front-end close. +Opening session #1 +Can resolve object: true +Disconnecting session #1 +Opening session #2 +Can resolve object: false +Error: +{ + code : -32000 + message : Could not find object with given id +} +
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/injected-script-discard.js b/third_party/WebKit/LayoutTests/inspector-protocol/injected-script-discard.js new file mode 100644 index 0000000..216776a --- /dev/null +++ b/third_party/WebKit/LayoutTests/inspector-protocol/injected-script-discard.js
@@ -0,0 +1,21 @@ +(async function(testRunner) { + testRunner.log('Tests that injected script is discarded upon front-end close.'); + var page = await testRunner.createPage(); + + testRunner.log('Opening session #1'); + var session = await page.createSession(); + var {result} = await session.protocol.Runtime.evaluate({expression: '({ handle : "handle" })' }); + var objectId = result.result.objectId; + var properties = await session.protocol.Runtime.getProperties({objectId: objectId, ownProperties: false}); + testRunner.log('Can resolve object: ' + !properties.error); + testRunner.log('Disconnecting session #1'); + await session.disconnect(); + + testRunner.log('Opening session #2'); + session = await page.createSession(); + properties = await session.protocol.Runtime.getProperties({objectId: objectId, ownProperties: false}); + testRunner.log('Can resolve object: ' + !properties.error); + testRunner.log('Error:'); + testRunner.log(properties.error); + testRunner.completeTest(); +})
diff --git a/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js b/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js index 9f1f904c..27f92e5 100644 --- a/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js +++ b/third_party/WebKit/LayoutTests/resources/bluetooth/bluetooth-helpers.js
@@ -25,8 +25,15 @@ // Load the Chromium-specific resources. let root = window.location.pathname.match(/.*LayoutTests/); - let resource_prefix = `${root}/resources`; - let gen_prefix = 'file:///gen/'; + let resource_prefix, gen_prefix; + if (root === null) { + // Use the correct aliases for tests using an HTTP server. + resource_prefix = `/js-test-resources`; + gen_prefix = `/gen`; + } else { + resource_prefix = `${root}/resources`; + gen_prefix = 'file:///gen/'; + } return loadScripts([ `${gen_prefix}/layout_test_data/mojo/public/js/mojo_bindings.js`, `${gen_prefix}/content/test/data/mojo_layouttest_test.mojom.js`,
diff --git a/third_party/WebKit/LayoutTests/typedcssom/cssMatrixComponent.html b/third_party/WebKit/LayoutTests/typedcssom/cssMatrixComponent.html index fe4f6ea..3920f6a 100644 --- a/third_party/WebKit/LayoutTests/typedcssom/cssMatrixComponent.html +++ b/third_party/WebKit/LayoutTests/typedcssom/cssMatrixComponent.html
@@ -72,19 +72,6 @@ } test(() => { - for (let param of testParams) { - let matrixComponent = new CSSMatrixComponent(param.input, {}); - assert_equals(matrixComponent.is2D, param.input.is2D); - matrixComponent = new CSSMatrixComponent(param.input, {is2D: undefined}); - assert_equals(matrixComponent.is2D, param.input.is2D); - matrixComponent = new CSSMatrixComponent(param.input, undefined); - assert_equals(matrixComponent.is2D, param.input.is2D); - matrixComponent = new CSSMatrixComponent(param.input, null); - assert_equals(matrixComponent.is2D, param.input.is2D); - } -}, "is2D value should be matrix's is2D when second parameter is not CSSMatrixComponentOptions"); - -test(() => { assert_throws(new TypeError(), () => { new CSSMatrixComponent(); }); assert_throws(new TypeError(), () => { new CSSMatrixComponent(0); }); assert_throws(new TypeError(), () => { new CSSMatrixComponent("string") });
diff --git a/third_party/WebKit/LayoutTests/typedcssom/stylevalue-subclasses/cssMatrixComponent.html b/third_party/WebKit/LayoutTests/typedcssom/stylevalue-subclasses/cssMatrixComponent.html new file mode 100644 index 0000000..28e7308 --- /dev/null +++ b/third_party/WebKit/LayoutTests/typedcssom/stylevalue-subclasses/cssMatrixComponent.html
@@ -0,0 +1,61 @@ +<!doctype html> +<meta charset="utf-8"> +<title>CSSMatrixComponent tests</title> +<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-cssmatrixcomponent-cssmatrixcomponent"> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../resources/testhelper.js"></script> +<script src="../resources/comparisons.js"></script> +<script> +'use strict'; + +const EPSILON = 1e-6; + +const gTestMatrices = [ + { + matrix: new DOMMatrix([0, -1, 3.14, -3.14, 10, 0]), + desc: 'a 2D matrix' + }, + { + matrix: new DOMMatrix([1.1, 1.2, -13, -1.4, 2, 0, -2, 4, 3.1, 3, 3, 3.4, -4.1, 42, 43, 4.4]), + desc: 'a 3D matrix' + }, +]; + +for (const {matrix, desc} of gTestMatrices) { + test(() => { + const component = new CSSMatrixComponent(matrix, { is2D: true }); + assert_matrix_approx_equals(component.matrix, matrix, EPSILON); + assert_true(component.is2D); + }, 'CSSMatrixComponent can be constructed from ' + desc + ' with is2D true'); + + test(() => { + const component = new CSSMatrixComponent(matrix, { is2D: false }); + assert_matrix_approx_equals(component.matrix, matrix, EPSILON); + assert_false(component.is2D); + }, 'CSSMatrixComponent can be constructed from ' + desc + ' with is2D false'); + + test(() => { + const component = new CSSMatrixComponent(matrix); + assert_matrix_approx_equals(component.matrix, matrix, EPSILON); + assert_equals(component.is2D, matrix.is2D); + }, 'CSSMatrixComponent can be constructed from ' + desc + ' without a CSSMatrixComponentOptions'); + + test(() => { + const component = new CSSMatrixComponent(matrix, null); + assert_matrix_approx_equals(component.matrix, matrix, EPSILON); + assert_equals(component.is2D, matrix.is2D); + }, 'CSSMatrixComponent can be constructed from ' + desc + ' with an invalid CSSMatrixComponentOptions'); + + test(() => { + let component = new CSSMatrixComponent(new DOMMatrixReadOnly([ + 0, 0, 0, 0, 0, 0 + ])); + + component.matrix = matrix; + assert_matrix_approx_equals(component.matrix, matrix, EPSILON); + }, 'CSSMatrixComponent.matrix can be updated to ' + desc); +} + +</script> +
diff --git a/third_party/WebKit/LayoutTests/typedcssom/the-stylepropertymap/iterable-expected.txt b/third_party/WebKit/LayoutTests/typedcssom/the-stylepropertymap/iterable-expected.txt deleted file mode 100644 index 3a03b286..0000000 --- a/third_party/WebKit/LayoutTests/typedcssom/the-stylepropertymap/iterable-expected.txt +++ /dev/null
@@ -1,8 +0,0 @@ -This is a testharness.js-based test. -PASS Iterating over an empty StylePropertyMap gives a zero-length array -PASS StylePropertyMap iterates properties in correct order -FAIL StylePropertyMap iterator returns CSS properties with the correct CSSStyleValue result is not defined -PASS StylePropertyMap iterator returns list-valued properties with the correct CSSStyleValue -PASS StylePropertyMap iterator returns custom properties with the correct CSSStyleValue -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/typedcssom/the-stylepropertymap/iterable.html b/third_party/WebKit/LayoutTests/typedcssom/the-stylepropertymap/iterable.html index 5546022..59a8e5b0 100644 --- a/third_party/WebKit/LayoutTests/typedcssom/the-stylepropertymap/iterable.html +++ b/third_party/WebKit/LayoutTests/typedcssom/the-stylepropertymap/iterable.html
@@ -25,7 +25,7 @@ test(() => { const styleMap = document.getElementById('target-multiple').attributeStyleMap; - const [key, value] = [...styleMap][2]; + const [key, result] = [...styleMap][2]; assert_equals(key, 'width'); assert_style_value_equals(result, CSS.px(10)); }, 'StylePropertyMap iterator returns CSS properties with the correct CSSStyleValue');
diff --git a/third_party/WebKit/LayoutTests/virtual/pwa-full-code-cache/http/tests/devtools/service-workers/service-worker-v8-cache-expected.txt b/third_party/WebKit/LayoutTests/virtual/pwa-full-code-cache/http/tests/devtools/service-workers/service-worker-v8-cache-expected.txt index c57a834..8441497 100644 --- a/third_party/WebKit/LayoutTests/virtual/pwa-full-code-cache/http/tests/devtools/service-workers/service-worker-v8-cache-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/pwa-full-code-cache/http/tests/devtools/service-workers/service-worker-v8-cache-expected.txt
@@ -28,7 +28,7 @@ startTime : <number> type : "v8.compile" } -Text details for v8.compile: :8000/devtools/service-workers/resources/v8-cache-script.js:1 +Text details for v8.compile: v8-cache-script.js:1 ----------------------------------------------- --- Trace events while executing scripts ------ v8.compile Properties:
diff --git a/third_party/WebKit/LayoutTests/virtual/threaded/http/tests/devtools/tracing/idle-callback.html b/third_party/WebKit/LayoutTests/virtual/threaded/http/tests/devtools/tracing/idle-callback.html deleted file mode 100644 index 81dda046..0000000 --- a/third_party/WebKit/LayoutTests/virtual/threaded/http/tests/devtools/tracing/idle-callback.html +++ /dev/null
@@ -1,52 +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(idleWarningAddOn) -{ - var callback; - var promise = new Promise((fulfill) => callback = fulfill); - var requestId = window.requestIdleCallback(idleCallback); - window.cancelIdleCallback(requestId); - window.requestIdleCallback(idleCallback); - function idleCallback() - { - window.requestIdleCallback(slowIdleCallback); - } - function slowIdleCallback(deadline) - { - while (deadline.timeRemaining()) {}; - var addOnDeadline = performance.now() + idleWarningAddOn; - while (performance.now() < addOnDeadline) {}; - if (callback) - callback(); - } - return promise; -} - -function test() -{ - InspectorTest.invokeAsyncWithTimeline(`(() => performActions(${TimelineModel.TimelineModel.Thresholds.IdleCallbackAddon}))`, finish); - - function finish() - { - InspectorTest.printTimelineRecordsWithDetails("RequestIdleCallback"); - InspectorTest.printTimelineRecordsWithDetails("CancelIdleCallback"); - InspectorTest.printTimelineRecordsWithDetails("FireIdleCallback"); - InspectorTest.completeTest(); - } -} - -if (!window.testRunner) - setTimeout(performActions, 2000); -</script> -</head> - -<body onload="runTest()"> -<p> -Tests Timeline events emitted when idle callback is scheduled and fired. -</p> - -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/virtual/threaded/http/tests/devtools/tracing/idle-callback.js b/third_party/WebKit/LayoutTests/virtual/threaded/http/tests/devtools/tracing/idle-callback.js new file mode 100644 index 0000000..53a0e85 --- /dev/null +++ b/third_party/WebKit/LayoutTests/virtual/threaded/http/tests/devtools/tracing/idle-callback.js
@@ -0,0 +1,41 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(async function() { + TestRunner.addResult(`Tests Timeline events emitted when idle callback is scheduled and fired.\n`); + await TestRunner.loadModule('performance_test_runner'); + await TestRunner.evaluateInPagePromise(` + function performActions(idleWarningAddOn) + { + var callback; + var promise = new Promise((fulfill) => callback = fulfill); + var requestId = window.requestIdleCallback(idleCallback); + window.cancelIdleCallback(requestId); + window.requestIdleCallback(idleCallback); + function idleCallback() + { + window.requestIdleCallback(slowIdleCallback); + } + function slowIdleCallback(deadline) + { + while (deadline.timeRemaining()) {}; + var addOnDeadline = performance.now() + idleWarningAddOn; + while (performance.now() < addOnDeadline) {}; + if (callback) + callback(); + } + return promise; + } + `); + + PerformanceTestRunner.invokeAsyncWithTimeline( + `(() => performActions(${TimelineModel.TimelineModel.Thresholds.IdleCallbackAddon}))`, finish); + + function finish() { + PerformanceTestRunner.printTimelineRecordsWithDetails('RequestIdleCallback'); + PerformanceTestRunner.printTimelineRecordsWithDetails('CancelIdleCallback'); + PerformanceTestRunner.printTimelineRecordsWithDetails('FireIdleCallback'); + TestRunner.completeTest(); + } +})();
diff --git a/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp b/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp index f0ebb52..73b22e4 100644 --- a/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp +++ b/third_party/WebKit/Source/bindings/core/v8/custom/V8CSSStyleDeclarationCustom.cpp
@@ -156,8 +156,10 @@ if (property_names.IsEmpty()) { for (int id = firstCSSProperty; id <= lastCSSProperty; ++id) { CSSPropertyID property_id = static_cast<CSSPropertyID>(id); - if (CSSProperty::Get(resolveCSSPropertyID(property_id)).IsEnabled()) - property_names.push_back(getJSPropertyName(property_id)); + const CSSProperty& property_class = + CSSProperty::Get(resolveCSSPropertyID(property_id)); + if (property_class.IsEnabled()) + property_names.push_back(property_class.GetJSPropertyName()); } std::sort(property_names.begin(), property_names.end(), WTF::CodePointCompareLessThan); @@ -229,7 +231,8 @@ value); ExceptionState exception_state( info.GetIsolate(), ExceptionState::kSetterContext, "CSSStyleDeclaration", - getPropertyName(resolveCSSPropertyID(unresolved_property))); + CSSProperty::Get(resolveCSSPropertyID(unresolved_property)) + .GetPropertyName()); impl->SetPropertyInternal(unresolved_property, String(), property_value, false, execution_context->GetSecureContextMode(), exception_state);
diff --git a/third_party/WebKit/Source/bindings/modules/v8/serialization/V8ScriptValueSerializerForModulesTest.cpp b/third_party/WebKit/Source/bindings/modules/v8/serialization/V8ScriptValueSerializerForModulesTest.cpp index 421b694..780a8a9 100644 --- a/third_party/WebKit/Source/bindings/modules/v8/serialization/V8ScriptValueSerializerForModulesTest.cpp +++ b/third_party/WebKit/Source/bindings/modules/v8/serialization/V8ScriptValueSerializerForModulesTest.cpp
@@ -13,6 +13,7 @@ #include "bindings/modules/v8/V8DOMFileSystem.h" #include "bindings/modules/v8/V8RTCCertificate.h" #include "bindings/modules/v8/serialization/V8ScriptValueDeserializerForModules.h" +#include "build/build_config.h" #include "core/typed_arrays/DOMArrayBuffer.h" #include "modules/crypto/CryptoResultImpl.h" #include "modules/filesystem/DOMFileSystem.h" @@ -143,7 +144,13 @@ 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a}; +// TODO(https://crbug.com/795627): This test is crashing on the Cast Audio Linux +// bot. +#if defined(OS_LINUX) +TEST(V8ScriptValueSerializerForModulesTest, DISABLED_RoundTripRTCCertificate) { +#else TEST(V8ScriptValueSerializerForModulesTest, RoundTripRTCCertificate) { +#endif V8TestingScope scope; // Make a certificate with the existing key above. @@ -168,7 +175,13 @@ EXPECT_EQ(kEcdsaCertificate, pem.Certificate()); } +// TODO(https://crbug.com/795627): This test is crashing on the Cast Audio Linux +// bot. +#if defined(OS_LINUX) +TEST(V8ScriptValueSerializerForModulesTest, DISABLED_DecodeRTCCertificate) { +#else TEST(V8ScriptValueSerializerForModulesTest, DecodeRTCCertificate) { +#endif V8TestingScope scope; // This is encoded data generated from Chromium (around M55). @@ -189,7 +202,14 @@ EXPECT_EQ(kEcdsaCertificate, pem.Certificate()); } +// TODO(https://crbug.com/795627): This test is crashing on the Cast Audio Linux +// bot. +#if defined(OS_LINUX) +TEST(V8ScriptValueSerializerForModulesTest, + DISABLED_DecodeInvalidRTCCertificate) { +#else TEST(V8ScriptValueSerializerForModulesTest, DecodeInvalidRTCCertificate) { +#endif V8TestingScope scope; // This is valid, except that "private" is not a valid private key PEM and
diff --git a/third_party/WebKit/Source/build/scripts/core/css/css_properties.py b/third_party/WebKit/Source/build/scripts/core/css/css_properties.py index 3295c7e..e137f6dc 100755 --- a/third_party/WebKit/Source/build/scripts/core/css/css_properties.py +++ b/third_party/WebKit/Source/build/scripts/core/css/css_properties.py
@@ -164,6 +164,7 @@ enum_for_css_property(alias['alias_for'])] updated_alias = aliased_property.copy() updated_alias['name'] = alias['name'] + updated_alias['property_class'] = alias['property_class'] updated_alias['alias_for'] = alias['alias_for'] updated_alias['property_id'] = enum_for_css_property_alias( alias['name'])
diff --git a/third_party/WebKit/Source/build/scripts/core/css/properties/make_css_property_base.py b/third_party/WebKit/Source/build/scripts/core/css/properties/make_css_property_base.py index 3dcd0fa..231b036d 100755 --- a/third_party/WebKit/Source/build/scripts/core/css/properties/make_css_property_base.py +++ b/third_party/WebKit/Source/build/scripts/core/css/properties/make_css_property_base.py
@@ -15,7 +15,7 @@ class PropertyClassData( - namedtuple('PropertyClassData', 'enum_value,property_id,classname,superclass')): + namedtuple('PropertyClassData', 'enum_value,property_id,classname,namespace_group')): pass @@ -24,28 +24,41 @@ super(CSSPropertyWriter, self).__init__([]) self._input_files = json5_file_paths self._outputs = { - 'CSSProperty.h': self.generate_property_header, - 'CSSProperty.cpp': self.generate_property_implementation, + 'CSSUnresolvedProperty.h': self.generate_unresolved_property_header, + 'CSSUnresolvedProperty.cpp': + self.generate_unresolved_property_implementation, + 'CSSProperty.h': self.generate_resolved_property_header, + 'CSSProperty.cpp': self.generate_resolved_property_implementation, } self._css_properties = css_properties.CSSProperties(json5_file_paths) # A list of (enum_value, property_id, property_classname) tuples. self._property_classes_by_id = [] + self._alias_classes_by_id = [] # Just a set of class names. self._shorthand_property_classes = set() self._longhand_property_classes = set() for property_ in self._css_properties.longhands: property_class = self.get_class(property_) self._property_classes_by_id.append(property_class) - self._longhand_property_classes.add(property_class.classname) + if property_class.classname != 'Longhand': + self._longhand_property_classes.add(property_class.classname) for property_ in self._css_properties.shorthands: property_class = self.get_class(property_) self._property_classes_by_id.append(property_class) self._shorthand_property_classes.add(property_class.classname) + for property_ in self._css_properties.aliases: + property_class = self.get_class(property_) + self._alias_classes_by_id.append(property_class) + if property_['longhands']: + self._shorthand_property_classes.add(property_class.classname) + elif property_class.classname != 'Longhand': + self._longhand_property_classes.add(property_class.classname) # Sort by enum value. self._property_classes_by_id.sort(key=lambda t: t.enum_value) + self._alias_classes_by_id.sort(key=lambda t: t.enum_value) def get_class(self, property_): """Gets the classname for a given property. @@ -65,41 +78,61 @@ "property_class value for {} should be None, True or a string".format( property_['name']) classname = property_['property_class'] - superclass = 'Shorthand' if property_['longhands'] else 'Longhand' + namespace_group = 'Shorthand' if property_['longhands'] else 'Longhand' if property_['property_class'] is None: classname = 'Longhand' - superclass = None + namespace_group = None if property_['property_class'] is True: classname = property_['upper_camel_name'] return PropertyClassData( enum_value=property_['enum_value'], property_id=property_['property_id'], classname=classname, - superclass=superclass) + namespace_group=namespace_group) @property def css_properties(self): return self._css_properties @template_expander.use_jinja( - 'core/css/properties/templates/CSSProperty.h.tmpl') - def generate_property_header(self): + 'core/css/properties/templates/CSSUnresolvedProperty.h.tmpl') + def generate_unresolved_property_header(self): return { 'input_files': self._input_files, 'property_classes_by_property_id': self._property_classes_by_id, + 'alias_classes_by_property_id': self._alias_classes_by_id, } @template_expander.use_jinja( - 'core/css/properties/templates/CSSProperty.cpp.tmpl') - def generate_property_implementation(self): + 'core/css/properties/templates/CSSUnresolvedProperty.cpp.tmpl') + def generate_unresolved_property_implementation(self): return { 'input_files': self._input_files, 'longhand_property_classnames': self._longhand_property_classes, 'shorthand_property_classnames': self._shorthand_property_classes, 'property_classes_by_property_id': self._property_classes_by_id, + 'alias_classes_by_property_id': self._alias_classes_by_id, + 'last_unresolved_property_id': + self._css_properties.last_unresolved_property_id, 'last_property_id': self._css_properties.last_property_id } + @template_expander.use_jinja( + 'core/css/properties/templates/CSSProperty.cpp.tmpl') + def generate_resolved_property_implementation(self): + return { + 'input_files': self._input_files, + 'property_classes_by_property_id': self._property_classes_by_id, + 'last_property_id': self._css_properties.last_property_id + } + + @template_expander.use_jinja( + 'core/css/properties/templates/CSSProperty.h.tmpl') + def generate_resolved_property_header(self): + return { + 'input_files': self._input_files, + 'property_classes_by_property_id': self._property_classes_by_id, + } if __name__ == '__main__': json5_generator.Maker(CSSPropertyWriter).main()
diff --git a/third_party/WebKit/Source/build/scripts/core/css/properties/make_css_property_headers.py b/third_party/WebKit/Source/build/scripts/core/css/properties/make_css_property_headers.py index f71a2b7..7784ca5 100755 --- a/third_party/WebKit/Source/build/scripts/core/css/properties/make_css_property_headers.py +++ b/third_party/WebKit/Source/build/scripts/core/css/properties/make_css_property_headers.py
@@ -41,10 +41,10 @@ self._outputs = {} output_dir = sys.argv[sys.argv.index('--output_dir') + 1] properties = self.css_properties.longhands - superclass = 'Longhand' + namespace_group = 'Longhand' if 'shorthands' in output_dir: properties = self.css_properties.shorthands - superclass = 'Shorthand' + namespace_group = 'Shorthand' for property_ in properties: if property_['property_class'] is None: continue @@ -54,13 +54,25 @@ self._property_methods[method_name] for method_name in property_['property_methods'] ] - property_['superclass'] = superclass + property_['namespace_group'] = namespace_group class_data = self.get_class(property_) self.calculate_apply_functions_to_declare(property_) self.populate_includes(property_) self._outputs[class_data.classname + '.h'] = ( self.generate_property_h_builder( class_data.classname, property_)) + for property_ in self.css_properties.aliases: + if ('shorthands' in output_dir and property_['longhands']) or \ + ('longhands' in output_dir and not property_['longhands']): + if property_['property_class'] is None: + continue + property_['unique'] = True + class_data = self.get_class(property_) + property_['namespace_group'] = namespace_group + self.populate_includes(property_) + self._outputs[class_data.classname + '.h'] = ( + self.generate_property_h_builder( + class_data.classname, property_)) def generate_property_h_builder(self, property_classname, property_): @template_expander.use_jinja( @@ -119,30 +131,36 @@ def populate_includes(self, property_): includes = [] - if property_['direction_aware_options']: - includes.append("core/StylePropertyShorthand.h") - if property_['runtime_flag']: - includes.append("platform/runtime_enabled_features.h") - if property_['should_implement_apply_functions']: - includes.append("core/css/resolver/StyleResolverState.h") - if property_['converter'] == "CSSPrimitiveValue": - includes.append("core/css/CSSPrimitiveValue.h") - includes.append("core/css/CSSPrimitiveValueMappings.h") - elif property_['converter'] == "CSSIdentifierValue": - includes.append("core/css/CSSIdentifierValue.h") - elif property_['converter']: - includes.append("core/css/CSSPrimitiveValueMappings.h") - includes.append("core/css/resolver/StyleBuilderConverter.h") - if property_['font']: - includes.append("core/css/resolver/FontBuilder.h") - elif property_['svg']: - includes.append("core/style/ComputedStyle.h") - includes.append("core/style/SVGComputedStyle.h") - else: - includes.append("core/style/ComputedStyle.h") - if (property_.get('custom_apply_args') and - property_.get('custom_apply_args').get('modifier_type') in ['Width', 'Slice', 'Outset']): - includes.append("core/css/properties/StyleBuildingUtils.h") + if property_['alias_for']: + includes.append("core/css/properties/CSSUnresolvedProperty.h") + else: + includes.append("core/css/properties/" + property_['namespace_group'] + ".h") + if property_['direction_aware_options']: + includes.append("core/StylePropertyShorthand.h") + if property_['runtime_flag']: + includes.append("platform/runtime_enabled_features.h") + if property_['should_implement_apply_functions']: + includes.append("core/css/resolver/StyleResolverState.h") + if property_['converter'] == "CSSPrimitiveValue": + includes.append("core/css/CSSPrimitiveValue.h") + includes.append("core/css/CSSPrimitiveValueMappings.h") + elif property_['converter'] == "CSSIdentifierValue": + includes.append("core/css/CSSIdentifierValue.h") + elif property_['converter']: + includes.append("core/css/CSSPrimitiveValueMappings.h") + includes.append("core/css/resolver/StyleBuilderConverter.h") + if property_['font']: + includes.append("core/css/resolver/FontBuilder.h") + elif property_['svg']: + includes.append("core/css/CSSPrimitiveValueMappings.h") + includes.append("core/style/ComputedStyle.h") + includes.append("core/style/SVGComputedStyle.h") + else: + includes.append("core/style/ComputedStyle.h") + if (property_.get('custom_apply_args') and + property_.get('custom_apply_args').get('modifier_type') + in ['Width', 'Slice', 'Outset']): + includes.append("core/css/properties/StyleBuildingUtils.h") includes.sort() property_['includes'] = includes
diff --git a/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSProperty.cpp.tmpl b/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSProperty.cpp.tmpl index 16c83bee..a436fefa 100644 --- a/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSProperty.cpp.tmpl +++ b/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSProperty.cpp.tmpl
@@ -8,54 +8,21 @@ #include "core/css/properties/CSSProperty.h" -#include "core/css/properties/longhands/Variable.h" -{% for property_class in longhand_property_classnames %} - {% if property_class != "Longhand" %} -#include "core/css/properties/longhands/{{property_class}}.h" - {% endif %} -{% endfor %} -{% for property_class in shorthand_property_classnames %} -#include "core/css/properties/shorthands/{{property_class}}.h" -{% endfor %} - namespace blink { -namespace { - -static constexpr Variable property_csspropertyvariable(CSSPropertyVariable); -{% for _, property_id, classname, superclass in property_classes_by_property_id %} - {% if superclass != None %} -static constexpr CSS{{superclass}}::{{classname}} property_{{property_id.lower()}}({{property_id}}); - {% else %} -static constexpr {{classname}} property_{{property_id.lower()}}({{property_id}}); - {% endif %} -{% endfor %} - -const CSSProperty& GetProperty(CSSPropertyID id) { - static constexpr const CSSProperty* const property_classes[] = { - &property_csspropertyvariable, // CSSPropertyVariable - {% for property_class_data in property_classes_by_property_id %} - &property_{{property_class_data.property_id.lower()}}, // {{property_class_data.property_id}} - {% endfor %} - }; - // Subtract 1 because CSSPropertyInvalid does not appear in the array. - return *property_classes[id - 1]; -} - -} // namespace const CSSProperty& GetCSSPropertyVariable() { - return property_csspropertyvariable; + return ToCSSProperty(CSSUnresolvedProperty::GetCSSPropertyVariableInternal()); } {% for property_class_data in property_classes_by_property_id %} const CSSProperty& Get{{property_class_data.property_id}}() { - return property_{{property_class_data.property_id.lower()}}; + return ToCSSProperty(CSSUnresolvedProperty::Get{{property_class_data.property_id}}Internal()); } {% endfor %} const CSSProperty& CSSProperty::Get(CSSPropertyID id) { DCHECK_NE(id, CSSPropertyInvalid); - DCHECK_LE(id, {{last_property_id}}); // last_property_id - return GetProperty(id); + DCHECK_LE(id, {{last_property_id}}); // last property id + return ToCSSProperty(CSSUnresolvedProperty::GetNonAliasProperty(id)); } } // namespace blink
diff --git a/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSProperty.h.tmpl b/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSProperty.h.tmpl index 26ef83c..8832a39 100644 --- a/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSProperty.h.tmpl +++ b/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSProperty.h.tmpl
@@ -11,9 +11,11 @@ #include "core/CSSPropertyNames.h" #include "core/css/CSSValue.h" +#include "core/css/properties/CSSUnresolvedProperty.h" #include "platform/heap/HeapAllocator.h" #include "platform/text/TextDirection.h" #include "platform/text/WritingMode.h" +#include "platform/wtf/text/WTFString.h" namespace blink { @@ -28,17 +30,14 @@ enum PhysicalBoxSide { kTopSide, kRightSide, kBottomSide, kLeftSide }; -class CSSProperty { +class CSSProperty : public CSSUnresolvedProperty { public: CORE_EXPORT static const CSSProperty& Get(CSSPropertyID); - explicit constexpr CSSProperty(CSSPropertyID id) : id_(id) {} + explicit constexpr CSSProperty(CSSPropertyID id) : CSSUnresolvedProperty(id) {} - // For backwards compatibility when passing around CSSProperty references. - // In case we need to call a function that hasn't been converted to using - // property classes yet. - CSSPropertyID PropertyID() const { return id_; } - bool IDEquals(CSSPropertyID id) const { return id_ == id; } + bool IsResolvedProperty() const override { return true; } + WTF::String GetJSPropertyName() const; virtual bool IsInterpolable() const { return false; } virtual bool IsInherited() const { return false; } @@ -90,11 +89,14 @@ TextDirection, WritingMode, const StylePropertyShorthand&); - - private: - const CSSPropertyID id_; }; +DEFINE_TYPE_CASTS(CSSProperty, + CSSUnresolvedProperty, + unresolved, + unresolved->IsResolvedProperty(), + unresolved.IsResolvedProperty()); + CORE_EXPORT const CSSProperty& GetCSSPropertyVariable(); {% for property_class_data in property_classes_by_property_id %} CORE_EXPORT const CSSProperty& Get{{property_class_data.property_id}}();
diff --git a/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSPropertySubclass.h.tmpl b/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSPropertySubclass.h.tmpl index be26280..6dd13f71 100644 --- a/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSPropertySubclass.h.tmpl +++ b/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSPropertySubclass.h.tmpl
@@ -6,11 +6,9 @@ {% from 'core/css/properties/templates/style_builder_functions.tmpl' import style_builder_functions %} {{source_files_for_generated_file(template_file, input_files)}} -#ifndef GEN_BLINK_CORE_CSS_PROPERTIES_{{property.superclass.upper()}}_{{property_classname}}_h -#define GEN_BLINK_CORE_CSS_PROPERTIES_{{property.superclass.upper()}}_{{property_classname}}_h +#ifndef GEN_BLINK_CORE_CSS_PROPERTIES_{{property.namespace_group.upper()}}_{{property_classname}}_h +#define GEN_BLINK_CORE_CSS_PROPERTIES_{{property.namespace_group.upper()}}_{{property_classname}}_h -#include "core/css/properties/{{property.superclass}}.h" -{# conditional includes - only used in some property classes #} {% for include in property.includes %} #include "{{include}}" {% endfor %} @@ -19,7 +17,7 @@ class CSSValue; -namespace CSS{{property.superclass}} { +namespace CSS{{property.namespace_group}} { {% if property.is_property %} {% if property.unique %} @@ -35,9 +33,23 @@ {% endif %} {% endif %} // See src/third_party/WebKit/Source/core/css/properties/README.md -class {{property_classname}} : public {{property.superclass}} { + {% if property.alias_for != None%} +class {{property_classname}} : public CSSUnresolvedProperty { public: - constexpr {{property_classname}}(CSSPropertyID id) : {{property.superclass}}(id) {} + constexpr {{property_classname}}(CSSPropertyID id) : CSSUnresolvedProperty(id) {} + {% else %} +class {{property_classname}} : public {{property.namespace_group}} { + public: + constexpr {{property_classname}}(CSSPropertyID id) : {{property.namespace_group}}(id) {} + {% endif %} + {% if property.unique %} + const char* GetPropertyName() const override { return "{{property.name}}\0"; } + const WTF::AtomicString& GetPropertyNameAtomicString() const override { + static const WTF::AtomicString& name = WTF::AtomicString("{{property.name}}\0"); + return name; + } + {% endif %} + {% if property.alias_for == None %} {% for property_method in property.property_methods %} {{property_method.return_type}} {{property_method.name}}{{property_method.parameters}} const override; {% endfor %} @@ -77,7 +89,7 @@ {% if property.direction_aware_options.logical_side == "width" %} const CSSProperty& ResolveDirectionAwareProperty( TextDirection direction, - WritingMode writing_mode) const override { + blink::WritingMode writing_mode) const override { if (IsHorizontalWritingMode(writing_mode)) return Get{{property.direction_aware_options.shorthand_for_physical_side}}Width(); return Get{{property.direction_aware_options.shorthand_for_physical_side}}Height(); @@ -85,7 +97,7 @@ {% elif property.direction_aware_options.logical_side == "height" %} const CSSProperty& ResolveDirectionAwareProperty( TextDirection direction, - WritingMode writing_mode) const override { + blink::WritingMode writing_mode) const override { if (IsHorizontalWritingMode(writing_mode)) return Get{{property.direction_aware_options.shorthand_for_physical_side}}Height(); return Get{{property.direction_aware_options.shorthand_for_physical_side}}Width(); @@ -93,7 +105,7 @@ {% else %} const CSSProperty& ResolveDirectionAwareProperty( TextDirection direction, - WritingMode writing_mode) const override { + blink::WritingMode writing_mode) const override { return Resolve{{property.direction_aware_options.logical_side[0].upper() + property.direction_aware_options.logical_side[1:]}}ToPhysicalProperty( direction, writing_mode, @@ -106,9 +118,10 @@ // Style builder functions {{style_builder_functions(property)}} {%- endif %} + {% endif %} }; -} // namespace CSS{{property.superclass}} +} // namespace CSS{{property.namespace_group}} } // namespace blink -#endif // GEN_BLINK_CORE_CSS_PROPERTIES_{{property.superclass.upper()}}_{{property_classname}}_h +#endif // GEN_BLINK_CORE_CSS_PROPERTIES_{{property.namespace_group.upper()}}_{{property_classname}}_h
diff --git a/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSUnresolvedProperty.cpp.tmpl b/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSUnresolvedProperty.cpp.tmpl new file mode 100644 index 0000000..8708bd17 --- /dev/null +++ b/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSUnresolvedProperty.cpp.tmpl
@@ -0,0 +1,82 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +{% from 'templates/macros.tmpl' import source_files_for_generated_file %} +{{source_files_for_generated_file(template_file, input_files)}} +// clang-format off + +#include "core/css/properties/CSSUnresolvedProperty.h" + +#include "core/css/properties/longhands/Variable.h" +{% for property_class in longhand_property_classnames %} + {% if property_class != "Longhand" %} +#include "core/css/properties/longhands/{{property_class}}.h" + {% endif %} +{% endfor %} +{% for property_class in shorthand_property_classnames %} +#include "core/css/properties/shorthands/{{property_class}}.h" +{% endfor %} + +namespace blink { +namespace { + +static constexpr Variable property_csspropertyvariable(CSSPropertyVariable); +{% for _, property_id, classname, namespace_group in property_classes_by_property_id %} + {% if namespace_group != None %} +static constexpr CSS{{namespace_group}}::{{classname}} property_{{property_id.lower()}}({{property_id}}); + {% else %} +static constexpr {{classname}} property_{{property_id.lower()}}({{property_id}}); + {% endif %} +{% endfor %} +{% for _, property_id, classname, namespace_group in alias_classes_by_property_id %} +static constexpr CSS{{namespace_group}}::{{classname}} property_{{property_id.lower()}}({{property_id}}); +{% endfor %} + +} // namespace + +const CSSUnresolvedProperty& CSSUnresolvedProperty::GetCSSPropertyVariableInternal() { + return property_csspropertyvariable; +} +{% for property_class_data in property_classes_by_property_id %} +const CSSUnresolvedProperty& CSSUnresolvedProperty::Get{{property_class_data.property_id}}Internal() { + return property_{{property_class_data.property_id.lower()}}; +} +{% endfor %} + +const CSSUnresolvedProperty* CSSUnresolvedProperty::GetAliasProperty(CSSPropertyID id) { + DCHECK_GT(id, {{last_property_id}}); // last property id + DCHECK_LE(id, {{last_unresolved_property_id}}); // last unresolved property id + switch (id) { + {% for property_class_data in alias_classes_by_property_id %} + case {{property_class_data.property_id}}: + return &property_{{property_class_data.property_id.lower()}}; + {% endfor %} + default: + NOTREACHED(); + return nullptr; + } +} + +const CSSUnresolvedProperty& CSSUnresolvedProperty::GetNonAliasProperty(CSSPropertyID id) { + DCHECK_NE(id, CSSPropertyInvalid); + DCHECK_LE(id, {{last_property_id}}); // last property id + static constexpr const CSSUnresolvedProperty* const property_classes[] = { + &property_csspropertyvariable, // CSSPropertyVariable + {% for property_class_data in property_classes_by_property_id %} + &property_{{property_class_data.property_id.lower()}}, // {{property_class_data.property_id}} + {% endfor %} + }; + // Subtract 1 because CSSPropertyInvalid does not appear in the array. + return *property_classes[id - 1]; +} + +const CSSUnresolvedProperty& CSSUnresolvedProperty::Get(CSSPropertyID id) { + DCHECK_NE(id, CSSPropertyInvalid); + DCHECK_LE(id, {{last_unresolved_property_id}}); // last_unresolved_property_id + if (id <= {{last_property_id}}) // last property id + return GetNonAliasProperty(id); + return *GetAliasProperty(id); +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSUnresolvedProperty.h.tmpl b/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSUnresolvedProperty.h.tmpl new file mode 100644 index 0000000..0331ce7c --- /dev/null +++ b/third_party/WebKit/Source/build/scripts/core/css/properties/templates/CSSUnresolvedProperty.h.tmpl
@@ -0,0 +1,57 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +{% from 'templates/macros.tmpl' import source_files_for_generated_file %} +{{source_files_for_generated_file(template_file, input_files)}} +// clang-format off + +#ifndef CSSUnresolvedProperty_h +#define CSSUnresolvedProperty_h + +#include "core/CSSPropertyNames.h" +#include "platform/wtf/text/WTFString.h" + +namespace blink { + +// TODO(crbug.com/793288): audit and consider redesigning how aliases are +// handled once more of project Ribbon is done and all use of aliases can be +// found and (hopefully) constrained. +class CSSUnresolvedProperty { + public: + CORE_EXPORT static const CSSUnresolvedProperty& Get(CSSPropertyID); + + explicit constexpr CSSUnresolvedProperty(CSSPropertyID id) : id_(id) {} + + // For backwards compatibility when passing around CSSUnresolvedProperty + // references. In case we need to call a function that hasn't been converted + // to using property classes yet. + CSSPropertyID PropertyID() const { return id_; } + bool IDEquals(CSSPropertyID id) const { return id_ == id; } + virtual bool IsResolvedProperty() const { return false; } + virtual const char* GetPropertyName() const { return getPropertyName(id_); } + virtual const WTF::AtomicString& GetPropertyNameAtomicString() const { + return getPropertyNameAtomicString(id_); + } + WTF::String GetPropertyNameString() const { + // We share the StringImpl with the AtomicStrings. + return GetPropertyNameAtomicString().GetString(); + } + + static const CSSUnresolvedProperty& GetCSSPropertyVariableInternal(); + {% for property_class_data in property_classes_by_property_id %} + static const CSSUnresolvedProperty& Get{{property_class_data.property_id}}Internal(); + {% endfor %} + + CORE_EXPORT static const CSSUnresolvedProperty* GetAliasProperty(CSSPropertyID); + + private: + const CSSPropertyID id_; + + protected: + static const CSSUnresolvedProperty& GetNonAliasProperty(CSSPropertyID); +}; + +} // namespace blink + +#endif // CSSUnresolvedProperty_h
diff --git a/third_party/WebKit/Source/build/scripts/core/style/computed_style_fields.py b/third_party/WebKit/Source/build/scripts/core/style/computed_style_fields.py index 6851c54..9e47951 100644 --- a/third_party/WebKit/Source/build/scripts/core/style/computed_style_fields.py +++ b/third_party/WebKit/Source/build/scripts/core/style/computed_style_fields.py
@@ -152,7 +152,6 @@ self.group = None # Method names - # TODO(nainar): Method name generation is inconsistent. Fix. self.getter_method_name = getter_method_name self.setter_method_name = setter_method_name self.internal_getter_method_name = method_name([self.name, 'internal'])
diff --git a/third_party/WebKit/Source/build/scripts/templates/CSSPropertyNames.cpp.tmpl b/third_party/WebKit/Source/build/scripts/templates/CSSPropertyNames.cpp.tmpl index d17d499..ebe5b9a 100644 --- a/third_party/WebKit/Source/build/scripts/templates/CSSPropertyNames.cpp.tmpl +++ b/third_party/WebKit/Source/build/scripts/templates/CSSPropertyNames.cpp.tmpl
@@ -82,33 +82,6 @@ return propertyString; } -String getPropertyNameString(CSSPropertyID id) { - // We share the StringImpl with the AtomicStrings. - return getPropertyNameAtomicString(id).GetString(); -} - -String getJSPropertyName(CSSPropertyID id) { - char result[maxCSSPropertyNameLength + 1]; - const char* cssPropertyName = getPropertyName(id); - const char* propertyNamePointer = cssPropertyName; - if (!propertyNamePointer) - return g_empty_string; - - char* resultPointer = result; - while (char character = *propertyNamePointer++) { - if (character == '-') { - char nextCharacter = *propertyNamePointer++; - if (!nextCharacter) - break; - character = (propertyNamePointer - 2 != cssPropertyName) - ? ToASCIIUpper(nextCharacter) : nextCharacter; - } - *resultPointer++ = character; - } - *resultPointer = '\0'; - return String(result); -} - CSSPropertyID cssPropertyID(const String& string) { return resolveCSSPropertyID(unresolvedCSSPropertyID(string));
diff --git a/third_party/WebKit/Source/build/scripts/templates/CSSPropertyNames.h.tmpl b/third_party/WebKit/Source/build/scripts/templates/CSSPropertyNames.h.tmpl index b85da03..b99b8a0 100644 --- a/third_party/WebKit/Source/build/scripts/templates/CSSPropertyNames.h.tmpl +++ b/third_party/WebKit/Source/build/scripts/templates/CSSPropertyNames.h.tmpl
@@ -32,10 +32,8 @@ const int numCSSPropertyIDs = lastUnresolvedCSSProperty + 1; const size_t maxCSSPropertyNameLength = {{max_name_length}}; -const char* getPropertyName(CSSPropertyID); -const WTF::AtomicString& getPropertyNameAtomicString(CSSPropertyID); -WTF::String CORE_EXPORT getPropertyNameString(CSSPropertyID); -WTF::String getJSPropertyName(CSSPropertyID); +CORE_EXPORT const char* getPropertyName(CSSPropertyID); +CORE_EXPORT const WTF::AtomicString& getPropertyNameAtomicString(CSSPropertyID); inline bool isCSSPropertyIDWithName(int id) {
diff --git a/third_party/WebKit/Source/core/BUILD.gn b/third_party/WebKit/Source/core/BUILD.gn index a281724..58022c99 100644 --- a/third_party/WebKit/Source/core/BUILD.gn +++ b/third_party/WebKit/Source/core/BUILD.gn
@@ -523,10 +523,14 @@ other_inputs = [ "../build/scripts/core/css/properties/templates/CSSProperty.cpp.tmpl", "../build/scripts/core/css/properties/templates/CSSProperty.h.tmpl", + "../build/scripts/core/css/properties/templates/CSSUnresolvedProperty.cpp.tmpl", + "../build/scripts/core/css/properties/templates/CSSUnresolvedProperty.h.tmpl", ] outputs = [ "$blink_core_output_dir/css/properties/CSSProperty.cpp", "$blink_core_output_dir/css/properties/CSSProperty.h", + "$blink_core_output_dir/css/properties/CSSUnresolvedProperty.cpp", + "$blink_core_output_dir/css/properties/CSSUnresolvedProperty.h", ] } @@ -549,6 +553,7 @@ "$blink_core_output_dir/css/properties/longhands/AnimationPlayState.h", "$blink_core_output_dir/css/properties/longhands/AutoOrString.h", "$blink_core_output_dir/css/properties/longhands/BackdropFilter.h", + "$blink_core_output_dir/css/properties/longhands/BackfaceVisibility.h", "$blink_core_output_dir/css/properties/longhands/BackgroundAttachment.h", "$blink_core_output_dir/css/properties/longhands/BackgroundBlendMode.h", "$blink_core_output_dir/css/properties/longhands/BackgroundBox.h", @@ -558,6 +563,7 @@ "$blink_core_output_dir/css/properties/longhands/BaselineShift.h", "$blink_core_output_dir/css/properties/longhands/BlockSizeOrLogicalHeight.h", "$blink_core_output_dir/css/properties/longhands/BorderBottomColor.h", + "$blink_core_output_dir/css/properties/longhands/BorderCollapse.h", "$blink_core_output_dir/css/properties/longhands/BorderImageOutset.h", "$blink_core_output_dir/css/properties/longhands/BorderImageRepeat.h", "$blink_core_output_dir/css/properties/longhands/BorderImageSlice.h", @@ -568,13 +574,20 @@ "$blink_core_output_dir/css/properties/longhands/BorderTopColor.h", "$blink_core_output_dir/css/properties/longhands/BorderWidthSide.h", "$blink_core_output_dir/css/properties/longhands/BoxShadow.h", + "$blink_core_output_dir/css/properties/longhands/BoxSizing.h", + "$blink_core_output_dir/css/properties/longhands/CaptionSide.h", "$blink_core_output_dir/css/properties/longhands/CaretColor.h", "$blink_core_output_dir/css/properties/longhands/Clip.h", "$blink_core_output_dir/css/properties/longhands/ClipPath.h", + "$blink_core_output_dir/css/properties/longhands/ClipRule.h", "$blink_core_output_dir/css/properties/longhands/Color.h", + "$blink_core_output_dir/css/properties/longhands/ColorInterpolation.h", + "$blink_core_output_dir/css/properties/longhands/ColorInterpolationFilters.h", + "$blink_core_output_dir/css/properties/longhands/ColorRendering.h", "$blink_core_output_dir/css/properties/longhands/ColumnCount.h", "$blink_core_output_dir/css/properties/longhands/ColumnGap.h", "$blink_core_output_dir/css/properties/longhands/ColumnRuleColor.h", + "$blink_core_output_dir/css/properties/longhands/ColumnRuleStyle.h", "$blink_core_output_dir/css/properties/longhands/ColumnRuleWidth.h", "$blink_core_output_dir/css/properties/longhands/ColumnSpan.h", "$blink_core_output_dir/css/properties/longhands/ColumnWidth.h", @@ -587,16 +600,30 @@ "$blink_core_output_dir/css/properties/longhands/Delay.h", "$blink_core_output_dir/css/properties/longhands/DescriptorOnly.h", "$blink_core_output_dir/css/properties/longhands/Direction.h", + "$blink_core_output_dir/css/properties/longhands/DominantBaseline.h", "$blink_core_output_dir/css/properties/longhands/Duration.h", + "$blink_core_output_dir/css/properties/longhands/EmptyCells.h", + "$blink_core_output_dir/css/properties/longhands/EpubCaptionSide.h", + "$blink_core_output_dir/css/properties/longhands/EpubTextCombine.h", + "$blink_core_output_dir/css/properties/longhands/EpubTextEmphasisColor.h", + "$blink_core_output_dir/css/properties/longhands/EpubTextEmphasisStyle.h", + "$blink_core_output_dir/css/properties/longhands/EpubTextOrientation.h", + "$blink_core_output_dir/css/properties/longhands/EpubTextTransform.h", + "$blink_core_output_dir/css/properties/longhands/EpubWordBreak.h", + "$blink_core_output_dir/css/properties/longhands/EpubWritingMode.h", "$blink_core_output_dir/css/properties/longhands/FillOrStrokeOpacity.h", + "$blink_core_output_dir/css/properties/longhands/FillRule.h", "$blink_core_output_dir/css/properties/longhands/Filter.h", "$blink_core_output_dir/css/properties/longhands/FlexBasis.h", + "$blink_core_output_dir/css/properties/longhands/FlexDirection.h", "$blink_core_output_dir/css/properties/longhands/FlexGrowOrShrink.h", + "$blink_core_output_dir/css/properties/longhands/FlexWrap.h", "$blink_core_output_dir/css/properties/longhands/FloodColor.h", "$blink_core_output_dir/css/properties/longhands/FloodOrStopOpacity.h", "$blink_core_output_dir/css/properties/longhands/FontDisplay.h", "$blink_core_output_dir/css/properties/longhands/FontFamily.h", "$blink_core_output_dir/css/properties/longhands/FontFeatureSettings.h", + "$blink_core_output_dir/css/properties/longhands/FontKerning.h", "$blink_core_output_dir/css/properties/longhands/FontSize.h", "$blink_core_output_dir/css/properties/longhands/FontSizeAdjust.h", "$blink_core_output_dir/css/properties/longhands/FontStretch.h", @@ -615,16 +642,19 @@ "$blink_core_output_dir/css/properties/longhands/GridTemplateLine.h", "$blink_core_output_dir/css/properties/longhands/Hyphens.h", "$blink_core_output_dir/css/properties/longhands/ImageOrientation.h", + "$blink_core_output_dir/css/properties/longhands/ImageRendering.h", "$blink_core_output_dir/css/properties/longhands/ImageSource.h", - "$blink_core_output_dir/css/properties/longhands/Inherited.h", "$blink_core_output_dir/css/properties/longhands/InlineSizeOrLogicalWidth.h", "$blink_core_output_dir/css/properties/longhands/JustifyItems.h", "$blink_core_output_dir/css/properties/longhands/JustifySelf.h", "$blink_core_output_dir/css/properties/longhands/LetterAndWordSpacing.h", "$blink_core_output_dir/css/properties/longhands/LightingColor.h", + "$blink_core_output_dir/css/properties/longhands/LineBreak.h", "$blink_core_output_dir/css/properties/longhands/LineHeight.h", "$blink_core_output_dir/css/properties/longhands/LineHeightStep.h", "$blink_core_output_dir/css/properties/longhands/ListStyleImage.h", + "$blink_core_output_dir/css/properties/longhands/ListStylePosition.h", + "$blink_core_output_dir/css/properties/longhands/ListStyleType.h", "$blink_core_output_dir/css/properties/longhands/MarginBottom.h", "$blink_core_output_dir/css/properties/longhands/MarginLeft.h", "$blink_core_output_dir/css/properties/longhands/MarginRight.h", @@ -652,6 +682,7 @@ "$blink_core_output_dir/css/properties/longhands/OutlineOffset.h", "$blink_core_output_dir/css/properties/longhands/OutlineWidth.h", "$blink_core_output_dir/css/properties/longhands/OverflowAnchor.h", + "$blink_core_output_dir/css/properties/longhands/OverflowWrap.h", "$blink_core_output_dir/css/properties/longhands/OverscrollBehaviorXOrY.h", "$blink_core_output_dir/css/properties/longhands/PaddingBottom.h", "$blink_core_output_dir/css/properties/longhands/PaddingLeft.h", @@ -662,6 +693,7 @@ "$blink_core_output_dir/css/properties/longhands/PaintStroke.h", "$blink_core_output_dir/css/properties/longhands/Perspective.h", "$blink_core_output_dir/css/properties/longhands/PerspectiveOrigin.h", + "$blink_core_output_dir/css/properties/longhands/PointerEvents.h", "$blink_core_output_dir/css/properties/longhands/PositionX.h", "$blink_core_output_dir/css/properties/longhands/PositionY.h", "$blink_core_output_dir/css/properties/longhands/Quotes.h", @@ -686,36 +718,66 @@ "$blink_core_output_dir/css/properties/longhands/ShapeLength.h", "$blink_core_output_dir/css/properties/longhands/ShapeMargin.h", "$blink_core_output_dir/css/properties/longhands/ShapeOutside.h", + "$blink_core_output_dir/css/properties/longhands/ShapeRendering.h", "$blink_core_output_dir/css/properties/longhands/Size.h", + "$blink_core_output_dir/css/properties/longhands/Speak.h", "$blink_core_output_dir/css/properties/longhands/StopColor.h", "$blink_core_output_dir/css/properties/longhands/StrokeDasharray.h", "$blink_core_output_dir/css/properties/longhands/StrokeDashoffsetOrStrokeWidth.h", + "$blink_core_output_dir/css/properties/longhands/StrokeLinecap.h", + "$blink_core_output_dir/css/properties/longhands/StrokeLinejoin.h", "$blink_core_output_dir/css/properties/longhands/StrokeMiterlimit.h", "$blink_core_output_dir/css/properties/longhands/TabSize.h", + "$blink_core_output_dir/css/properties/longhands/TextAlign.h", + "$blink_core_output_dir/css/properties/longhands/TextAlignLast.h", + "$blink_core_output_dir/css/properties/longhands/TextAnchor.h", + "$blink_core_output_dir/css/properties/longhands/TextCombineUpright.h", "$blink_core_output_dir/css/properties/longhands/TextDecorationColor.h", "$blink_core_output_dir/css/properties/longhands/TextDecorationLine.h", "$blink_core_output_dir/css/properties/longhands/TextDecorationStyle.h", "$blink_core_output_dir/css/properties/longhands/TextIndent.h", "$blink_core_output_dir/css/properties/longhands/TextJustify.h", + "$blink_core_output_dir/css/properties/longhands/TextOrientation.h", + "$blink_core_output_dir/css/properties/longhands/TextRendering.h", "$blink_core_output_dir/css/properties/longhands/TextShadow.h", "$blink_core_output_dir/css/properties/longhands/TextSizeAdjust.h", + "$blink_core_output_dir/css/properties/longhands/TextTransform.h", "$blink_core_output_dir/css/properties/longhands/TextUnderlinePosition.h", "$blink_core_output_dir/css/properties/longhands/TimingFunction.h", "$blink_core_output_dir/css/properties/longhands/TouchAction.h", "$blink_core_output_dir/css/properties/longhands/Transform.h", "$blink_core_output_dir/css/properties/longhands/TransformBox.h", "$blink_core_output_dir/css/properties/longhands/TransformOrigin.h", + "$blink_core_output_dir/css/properties/longhands/TransformStyle.h", "$blink_core_output_dir/css/properties/longhands/TransitionProperty.h", "$blink_core_output_dir/css/properties/longhands/Translate.h", "$blink_core_output_dir/css/properties/longhands/UnicodeBidi.h", + "$blink_core_output_dir/css/properties/longhands/UserSelect.h", "$blink_core_output_dir/css/properties/longhands/VerticalAlign.h", "$blink_core_output_dir/css/properties/longhands/Visibility.h", + "$blink_core_output_dir/css/properties/longhands/WebkitAlignContent.h", + "$blink_core_output_dir/css/properties/longhands/WebkitAlignItems.h", + "$blink_core_output_dir/css/properties/longhands/WebkitAlignSelf.h", + "$blink_core_output_dir/css/properties/longhands/WebkitAnimationDelay.h", + "$blink_core_output_dir/css/properties/longhands/WebkitAnimationDirection.h", + "$blink_core_output_dir/css/properties/longhands/WebkitAnimationDuration.h", + "$blink_core_output_dir/css/properties/longhands/WebkitAnimationFillMode.h", + "$blink_core_output_dir/css/properties/longhands/WebkitAnimationIterationCount.h", + "$blink_core_output_dir/css/properties/longhands/WebkitAnimationName.h", + "$blink_core_output_dir/css/properties/longhands/WebkitAnimationPlayState.h", + "$blink_core_output_dir/css/properties/longhands/WebkitAnimationTimingFunction.h", + "$blink_core_output_dir/css/properties/longhands/WebkitBackfaceVisibility.h", + "$blink_core_output_dir/css/properties/longhands/WebkitBackgroundClip.h", + "$blink_core_output_dir/css/properties/longhands/WebkitBackgroundOrigin.h", + "$blink_core_output_dir/css/properties/longhands/WebkitBackgroundSize.h", "$blink_core_output_dir/css/properties/longhands/WebkitBorderAfterColor.h", "$blink_core_output_dir/css/properties/longhands/WebkitBorderAfterStyle.h", "$blink_core_output_dir/css/properties/longhands/WebkitBorderAfterWidth.h", "$blink_core_output_dir/css/properties/longhands/WebkitBorderBeforeColor.h", "$blink_core_output_dir/css/properties/longhands/WebkitBorderBeforeStyle.h", "$blink_core_output_dir/css/properties/longhands/WebkitBorderBeforeWidth.h", + "$blink_core_output_dir/css/properties/longhands/WebkitBorderBottomLeftRadius.h", + "$blink_core_output_dir/css/properties/longhands/WebkitBorderBottomRightRadius.h", "$blink_core_output_dir/css/properties/longhands/WebkitBorderEndColor.h", "$blink_core_output_dir/css/properties/longhands/WebkitBorderEndStyle.h", "$blink_core_output_dir/css/properties/longhands/WebkitBorderEndWidth.h", @@ -724,15 +786,35 @@ "$blink_core_output_dir/css/properties/longhands/WebkitBorderStartColor.h", "$blink_core_output_dir/css/properties/longhands/WebkitBorderStartStyle.h", "$blink_core_output_dir/css/properties/longhands/WebkitBorderStartWidth.h", + "$blink_core_output_dir/css/properties/longhands/WebkitBorderTopLeftRadius.h", + "$blink_core_output_dir/css/properties/longhands/WebkitBorderTopRightRadius.h", + "$blink_core_output_dir/css/properties/longhands/WebkitBoxDirection.h", "$blink_core_output_dir/css/properties/longhands/WebkitBoxFlex.h", "$blink_core_output_dir/css/properties/longhands/WebkitBoxFlexGroup.h", "$blink_core_output_dir/css/properties/longhands/WebkitBoxOrdinalGroup.h", "$blink_core_output_dir/css/properties/longhands/WebkitBoxReflect.h", - "$blink_core_output_dir/css/properties/longhands/WebkitTapHighlightColor.h", - "$blink_core_output_dir/css/properties/longhands/WebkitTextEmphasisColor.h", - "$blink_core_output_dir/css/properties/longhands/WebkitTextFillColor.h", + "$blink_core_output_dir/css/properties/longhands/WebkitBoxShadow.h", + "$blink_core_output_dir/css/properties/longhands/WebkitBoxSizing.h", + "$blink_core_output_dir/css/properties/longhands/WebkitClipPath.h", + "$blink_core_output_dir/css/properties/longhands/WebkitColumnCount.h", + "$blink_core_output_dir/css/properties/longhands/WebkitColumnGap.h", + "$blink_core_output_dir/css/properties/longhands/WebkitColumnRuleColor.h", + "$blink_core_output_dir/css/properties/longhands/WebkitColumnRuleStyle.h", + "$blink_core_output_dir/css/properties/longhands/WebkitColumnRuleWidth.h", + "$blink_core_output_dir/css/properties/longhands/WebkitColumnSpan.h", + "$blink_core_output_dir/css/properties/longhands/WebkitColumnWidth.h", + "$blink_core_output_dir/css/properties/longhands/WebkitFilter.h", + "$blink_core_output_dir/css/properties/longhands/WebkitFlexBasis.h", + "$blink_core_output_dir/css/properties/longhands/WebkitFlexDirection.h", + "$blink_core_output_dir/css/properties/longhands/WebkitFlexGrow.h", + "$blink_core_output_dir/css/properties/longhands/WebkitFlexShrink.h", + "$blink_core_output_dir/css/properties/longhands/WebkitFlexWrap.h", + "$blink_core_output_dir/css/properties/longhands/WebkitFontFeatureSettings.h", "$blink_core_output_dir/css/properties/longhands/WebkitFontSizeDelta.h", + "$blink_core_output_dir/css/properties/longhands/WebkitFontSmoothing.h", "$blink_core_output_dir/css/properties/longhands/WebkitHighlight.h", + "$blink_core_output_dir/css/properties/longhands/WebkitJustifyContent.h", + "$blink_core_output_dir/css/properties/longhands/WebkitLineBreak.h", "$blink_core_output_dir/css/properties/longhands/WebkitLineClamp.h", "$blink_core_output_dir/css/properties/longhands/WebkitMarginAfter.h", "$blink_core_output_dir/css/properties/longhands/WebkitMarginBefore.h", @@ -745,20 +827,51 @@ "$blink_core_output_dir/css/properties/longhands/WebkitMaskClip.h", "$blink_core_output_dir/css/properties/longhands/WebkitMaskComposite.h", "$blink_core_output_dir/css/properties/longhands/WebkitMaskOrigin.h", + "$blink_core_output_dir/css/properties/longhands/WebkitOpacity.h", + "$blink_core_output_dir/css/properties/longhands/WebkitOrder.h", "$blink_core_output_dir/css/properties/longhands/WebkitOriginX.h", "$blink_core_output_dir/css/properties/longhands/WebkitOriginY.h", "$blink_core_output_dir/css/properties/longhands/WebkitPaddingAfter.h", "$blink_core_output_dir/css/properties/longhands/WebkitPaddingBefore.h", "$blink_core_output_dir/css/properties/longhands/WebkitPaddingEnd.h", "$blink_core_output_dir/css/properties/longhands/WebkitPaddingStart.h", + "$blink_core_output_dir/css/properties/longhands/WebkitPerspective.h", + "$blink_core_output_dir/css/properties/longhands/WebkitPerspectiveOrigin.h", + "$blink_core_output_dir/css/properties/longhands/WebkitPrintColorAdjust.h", + "$blink_core_output_dir/css/properties/longhands/WebkitRtlOrdering.h", + "$blink_core_output_dir/css/properties/longhands/WebkitRubyPosition.h", + "$blink_core_output_dir/css/properties/longhands/WebkitShapeImageThreshold.h", + "$blink_core_output_dir/css/properties/longhands/WebkitShapeMargin.h", + "$blink_core_output_dir/css/properties/longhands/WebkitShapeOutside.h", + "$blink_core_output_dir/css/properties/longhands/WebkitTapHighlightColor.h", + "$blink_core_output_dir/css/properties/longhands/WebkitTextCombine.h", "$blink_core_output_dir/css/properties/longhands/WebkitTextDecorationsInEffect.h", + "$blink_core_output_dir/css/properties/longhands/WebkitTextEmphasisColor.h", "$blink_core_output_dir/css/properties/longhands/WebkitTextEmphasisPosition.h", "$blink_core_output_dir/css/properties/longhands/WebkitTextEmphasisStyle.h", + "$blink_core_output_dir/css/properties/longhands/WebkitTextFillColor.h", + "$blink_core_output_dir/css/properties/longhands/WebkitTextOrientation.h", + "$blink_core_output_dir/css/properties/longhands/WebkitTextSecurity.h", + "$blink_core_output_dir/css/properties/longhands/WebkitTextSizeAdjust.h", "$blink_core_output_dir/css/properties/longhands/WebkitTextStrokeColor.h", "$blink_core_output_dir/css/properties/longhands/WebkitTextStrokeWidth.h", + "$blink_core_output_dir/css/properties/longhands/WebkitTransform.h", + "$blink_core_output_dir/css/properties/longhands/WebkitTransformOrigin.h", "$blink_core_output_dir/css/properties/longhands/WebkitTransformOriginZ.h", + "$blink_core_output_dir/css/properties/longhands/WebkitTransformStyle.h", + "$blink_core_output_dir/css/properties/longhands/WebkitTransitionTimingFunction.h", + "$blink_core_output_dir/css/properties/longhands/WebkitTransitionDelay.h", + "$blink_core_output_dir/css/properties/longhands/WebkitTransitionDuration.h", + "$blink_core_output_dir/css/properties/longhands/WebkitTransitionProperty.h", + "$blink_core_output_dir/css/properties/longhands/WebkitUserModify.h", + "$blink_core_output_dir/css/properties/longhands/WebkitUserSelect.h", + "$blink_core_output_dir/css/properties/longhands/WebkitWritingMode.h", + "$blink_core_output_dir/css/properties/longhands/WhiteSpace.h", "$blink_core_output_dir/css/properties/longhands/WidthOrHeight.h", "$blink_core_output_dir/css/properties/longhands/WillChange.h", + "$blink_core_output_dir/css/properties/longhands/WordBreak.h", + "$blink_core_output_dir/css/properties/longhands/WordWrap.h", + "$blink_core_output_dir/css/properties/longhands/WritingMode.h", "$blink_core_output_dir/css/properties/longhands/ZIndex.h", "$blink_core_output_dir/css/properties/longhands/Zoom.h", ] @@ -789,6 +902,7 @@ "$blink_core_output_dir/css/properties/shorthands/BorderWidth.h", "$blink_core_output_dir/css/properties/shorthands/ColumnRule.h", "$blink_core_output_dir/css/properties/shorthands/Columns.h", + "$blink_core_output_dir/css/properties/shorthands/EpubTextEmphasis.h", "$blink_core_output_dir/css/properties/shorthands/Flex.h", "$blink_core_output_dir/css/properties/shorthands/FlexFlow.h", "$blink_core_output_dir/css/properties/shorthands/Font.h", @@ -821,19 +935,26 @@ "$blink_core_output_dir/css/properties/shorthands/ScrollSnapMarginInline.h", "$blink_core_output_dir/css/properties/shorthands/TextDecoration.h", "$blink_core_output_dir/css/properties/shorthands/Transition.h", + "$blink_core_output_dir/css/properties/shorthands/WebkitAnimation.h", "$blink_core_output_dir/css/properties/shorthands/WebkitBorderAfter.h", "$blink_core_output_dir/css/properties/shorthands/WebkitBorderBefore.h", "$blink_core_output_dir/css/properties/shorthands/WebkitBorderEnd.h", + "$blink_core_output_dir/css/properties/shorthands/WebkitBorderRadius.h", "$blink_core_output_dir/css/properties/shorthands/WebkitBorderStart.h", "$blink_core_output_dir/css/properties/shorthands/WebkitColumnBreakAfter.h", "$blink_core_output_dir/css/properties/shorthands/WebkitColumnBreakBefore.h", "$blink_core_output_dir/css/properties/shorthands/WebkitColumnBreakInside.h", + "$blink_core_output_dir/css/properties/shorthands/WebkitColumnRule.h", + "$blink_core_output_dir/css/properties/shorthands/WebkitColumns.h", + "$blink_core_output_dir/css/properties/shorthands/WebkitFlex.h", + "$blink_core_output_dir/css/properties/shorthands/WebkitFlexFlow.h", "$blink_core_output_dir/css/properties/shorthands/WebkitMarginCollapse.h", "$blink_core_output_dir/css/properties/shorthands/WebkitMaskBoxImage.h", "$blink_core_output_dir/css/properties/shorthands/WebkitMaskPosition.h", "$blink_core_output_dir/css/properties/shorthands/WebkitMaskRepeat.h", "$blink_core_output_dir/css/properties/shorthands/WebkitTextEmphasis.h", "$blink_core_output_dir/css/properties/shorthands/WebkitTextStroke.h", + "$blink_core_output_dir/css/properties/shorthands/WebkitTransition.h", ] }
diff --git a/third_party/WebKit/Source/core/animation/AnimationInputHelpers.cpp b/third_party/WebKit/Source/core/animation/AnimationInputHelpers.cpp index 13a8a8a2..7774e5c 100644 --- a/third_party/WebKit/Source/core/animation/AnimationInputHelpers.cpp +++ b/third_party/WebKit/Source/core/animation/AnimationInputHelpers.cpp
@@ -31,25 +31,25 @@ return property.Substring(kSVGPrefixLength); } -static String CSSPropertyToKeyframeAttribute(CSSPropertyID property) { - DCHECK_NE(property, CSSPropertyInvalid); - DCHECK_NE(property, CSSPropertyVariable); +static String CSSPropertyToKeyframeAttribute(const CSSProperty& property) { + DCHECK_NE(property.PropertyID(), CSSPropertyInvalid); + DCHECK_NE(property.PropertyID(), CSSPropertyVariable); - switch (property) { + switch (property.PropertyID()) { case CSSPropertyFloat: return "cssFloat"; case CSSPropertyOffset: return "cssOffset"; default: - return getJSPropertyName(property); + return property.GetJSPropertyName(); } } static String PresentationAttributeToKeyframeAttribute( - CSSPropertyID presentation_attribute) { + const CSSProperty& presentation_attribute) { StringBuilder builder; builder.Append(kSVGPrefix, kSVGPrefixLength); - builder.Append(getPropertyName(presentation_attribute)); + builder.Append(presentation_attribute.GetPropertyName()); return builder.ToString(); } @@ -272,13 +272,12 @@ if (property.IsCSSProperty()) { return property.IsCSSCustomProperty() ? property.CustomPropertyName() - : CSSPropertyToKeyframeAttribute( - property.GetCSSProperty().PropertyID()); + : CSSPropertyToKeyframeAttribute(property.GetCSSProperty()); } if (property.IsPresentationAttribute()) { return PresentationAttributeToKeyframeAttribute( - property.PresentationAttribute().PropertyID()); + property.PresentationAttribute()); } DCHECK(property.IsSVGAttribute());
diff --git a/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp b/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp index 49898d0..66542d8 100644 --- a/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp +++ b/third_party/WebKit/Source/core/animation/CompositorAnimations.cpp
@@ -221,8 +221,7 @@ if (property.IsCSSCustomProperty()) { builder.Append(property.CustomPropertyName()); } else { - builder.Append( - getPropertyName(property.GetCSSProperty().PropertyID())); + builder.Append(property.GetCSSProperty().GetPropertyName()); } return FailureCode::Actionable(builder.ToString()); }
diff --git a/third_party/WebKit/Source/core/animation/StringKeyframe.h b/third_party/WebKit/Source/core/animation/StringKeyframe.h index a4e0995..acc9943 100644 --- a/third_party/WebKit/Source/core/animation/StringKeyframe.h +++ b/third_party/WebKit/Source/core/animation/StringKeyframe.h
@@ -6,7 +6,7 @@ #define StringKeyframe_h #include "core/animation/Keyframe.h" -#include "core/css/MutableCSSPropertyValueSet.h" +#include "core/css/CSSPropertyValueSet.h" #include "platform/wtf/HashMap.h"
diff --git a/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp b/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp index ecd465a9c..3c18bfe 100644 --- a/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp +++ b/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp
@@ -613,7 +613,7 @@ if (property.IsCSSCustomProperty()) { animation->setId(property.CustomPropertyName()); } else { - animation->setId(getPropertyName(property.GetCSSProperty().PropertyID())); + animation->setId(property.GetCSSProperty().GetPropertyName()); } // Set the current time as the start time for retargeted transitions if (retargeted_compositor_transitions.Contains(property)) { @@ -1178,7 +1178,7 @@ String property_name = property_.IsCSSCustomProperty() ? property_.CustomPropertyName() - : getPropertyNameString(property_.GetCSSProperty().PropertyID()); + : property_.GetCSSProperty().GetPropertyNameString(); const Timing& timing = animation_node.SpecifiedTiming(); double elapsed_time = timing.iteration_duration; const AtomicString& event_type = EventTypeNames::transitionend;
diff --git a/third_party/WebKit/Source/core/css/BUILD.gn b/third_party/WebKit/Source/core/css/BUILD.gn index 66812ea..b46a354f 100644 --- a/third_party/WebKit/Source/core/css/BUILD.gn +++ b/third_party/WebKit/Source/core/css/BUILD.gn
@@ -207,8 +207,6 @@ "FontSizeFunctions.cpp", "FontSizeFunctions.h", "HashTools.h", - "ImmutableCSSPropertyValueSet.cpp", - "ImmutableCSSPropertyValueSet.h", "KeyframeStyleRuleCSSStyleDeclaration.cpp", "KeyframeStyleRuleCSSStyleDeclaration.h", "LocalFontFaceSource.cpp", @@ -236,8 +234,6 @@ "MediaValuesDynamic.h", "MediaValuesInitialViewport.cpp", "MediaValuesInitialViewport.h", - "MutableCSSPropertyValueSet.cpp", - "MutableCSSPropertyValueSet.h", "OffscreenFontSelector.cpp", "OffscreenFontSelector.h", "PageRuleCollector.cpp", @@ -378,7 +374,6 @@ "parser/CSSAtRuleID.h", "parser/CSSLazyParsingState.cpp", "parser/CSSLazyParsingState.h", - "parser/CSSLazyPropertyParser.h", "parser/CSSLazyPropertyParserImpl.cpp", "parser/CSSLazyPropertyParserImpl.h", "parser/CSSParser.cpp",
diff --git a/third_party/WebKit/Source/core/css/CSSCalculationValueTest.cpp b/third_party/WebKit/Source/core/css/CSSCalculationValueTest.cpp index c8514098..28e08f5 100644 --- a/third_party/WebKit/Source/core/css/CSSCalculationValueTest.cpp +++ b/third_party/WebKit/Source/core/css/CSSCalculationValueTest.cpp
@@ -31,8 +31,8 @@ #include "core/css/CSSCalculationValue.h" #include "core/css/CSSPrimitiveValue.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/css/CSSToLengthConversionData.h" -#include "core/css/MutableCSSPropertyValueSet.h" #include "core/layout/api/LayoutViewItem.h" #include "core/style/ComputedStyle.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp b/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp index c202bb27..9529fe9 100644 --- a/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp +++ b/third_party/WebKit/Source/core/css/CSSComputedStyleDeclaration.cpp
@@ -180,13 +180,13 @@ return static_cast<CSSValueID>(CSSValueXxSmall + keyword_size - 1); } -void LogUnimplementedPropertyID(CSSPropertyID property_id) { +void LogUnimplementedPropertyID(const CSSProperty& property) { DEFINE_STATIC_LOCAL(HashSet<CSSPropertyID>, property_id_set, ()); - if (!property_id_set.insert(property_id).is_new_entry) + if (!property_id_set.insert(property.PropertyID()).is_new_entry) return; DLOG(ERROR) << "Blink does not yet implement getComputedStyle for '" - << getPropertyName(property_id) << "'."; + << property.GetPropertyName() << "'."; } } // namespace @@ -220,7 +220,7 @@ for (unsigned i = 0; i < properties.size(); i++) { if (i) result.Append(' '); - result.Append(getPropertyName(properties[i]->PropertyID())); + result.Append(properties[i]->GetPropertyName()); result.Append(": "); result.Append(GetPropertyValue(properties[i]->PropertyID())); result.Append(';'); @@ -362,7 +362,7 @@ if (value) return value; - LogUnimplementedPropertyID(property_class.PropertyID()); + LogUnimplementedPropertyID(property_class); return nullptr; } @@ -384,7 +384,7 @@ if (i >= length()) return ""; - return getPropertyNameString(ComputableProperties()[i]->PropertyID()); + return ComputableProperties()[i]->GetPropertyNameString(); } bool CSSComputedStyleDeclaration::CssPropertyMatches( @@ -508,7 +508,8 @@ exception_state.ThrowDOMException( kNoModificationAllowedError, "These styles are computed, and therefore the '" + - getPropertyNameString(id) + "' property is read-only."); + CSSProperty::Get(id).GetPropertyNameString() + + "' property is read-only."); } void CSSComputedStyleDeclaration::Trace(blink::Visitor* visitor) {
diff --git a/third_party/WebKit/Source/core/css/CSSCustomIdentValue.cpp b/third_party/WebKit/Source/core/css/CSSCustomIdentValue.cpp index 2604f82..80836e6d 100644 --- a/third_party/WebKit/Source/core/css/CSSCustomIdentValue.cpp +++ b/third_party/WebKit/Source/core/css/CSSCustomIdentValue.cpp
@@ -5,6 +5,7 @@ #include "core/css/CSSCustomIdentValue.h" #include "core/css/CSSMarkup.h" +#include "core/css/properties/CSSUnresolvedProperty.h" #include "platform/wtf/text/StringBuilder.h" #include "platform/wtf/text/WTFString.h" @@ -21,8 +22,10 @@ } String CSSCustomIdentValue::CustomCSSText() const { - if (IsKnownPropertyID()) - return getPropertyNameAtomicString(property_id_); + if (IsKnownPropertyID()) { + return CSSUnresolvedProperty::Get(property_id_) + .GetPropertyNameAtomicString(); + } StringBuilder builder; SerializeIdentifier(string_, builder); return builder.ToString();
diff --git a/third_party/WebKit/Source/core/css/CSSProperties.json5 b/third_party/WebKit/Source/core/css/CSSProperties.json5 index ce4ee24..76950d3b 100644 --- a/third_party/WebKit/Source/core/css/CSSProperties.json5 +++ b/third_party/WebKit/Source/core/css/CSSProperties.json5
@@ -492,7 +492,7 @@ }, { name: "font-kerning", - property_class: "Inherited", + property_class: true, inherited: true, font: true, name_for_methods: "Kerning", @@ -623,7 +623,7 @@ }, { name: "-webkit-font-smoothing", - property_class: "Inherited", + property_class: true, inherited: true, font: true, type_name: "FontSmoothingMode", @@ -640,7 +640,7 @@ }, { name: "text-orientation", - property_class: "Inherited", + property_class: true, inherited: true, field_group: "*", field_template: "keyword", @@ -652,7 +652,7 @@ }, { name: "-webkit-text-orientation", - property_class: "Inherited", + property_class: true, inherited: true, type_name: "TextOrientation", custom_apply_functions_value: true, @@ -660,7 +660,7 @@ }, { name: "writing-mode", - property_class: "Inherited", + property_class: true, inherited: true, field_template: "keyword", include_paths: ["platform/text/WritingMode.h"], @@ -672,7 +672,7 @@ }, { name: "-webkit-writing-mode", - property_class: "Inherited", + property_class: true, inherited: true, type_name: "WritingMode", custom_apply_functions_value: true, @@ -680,7 +680,7 @@ }, { name: "text-rendering", - property_class: "Inherited", + property_class: true, inherited: true, font: true, type_name: "TextRenderingMode", @@ -754,6 +754,7 @@ }, { name: "backface-visibility", + property_class: true, field_group: "*", field_template: "keyword", keywords: ["visible", "hidden"], @@ -909,7 +910,7 @@ }, { name: "border-collapse", - property_class: "Inherited", + property_class: true, independent: true, inherited: true, field_template: "keyword", @@ -1123,6 +1124,7 @@ }, { name: "box-sizing", + property_class: true, field_group: "box", field_template: "keyword", keywords: ["content-box", "border-box"], @@ -1166,7 +1168,7 @@ }, { name: "caption-side", - property_class: "Inherited", + property_class: true, independent: true, inherited: true, field_template: "keyword", @@ -1222,27 +1224,27 @@ }, { name: "clip-rule", - property_class: "Inherited", + property_class: true, inherited: true, svg: true, type_name: "WindRule", }, { name: "color-interpolation", - property_class: "Inherited", + property_class: true, inherited: true, svg: true, }, { name: "color-interpolation-filters", - property_class: "Inherited", + property_class: true, inherited: true, svg: true, type_name: "EColorInterpolation", }, { name: "color-rendering", - property_class: "Inherited", + property_class: true, inherited: true, svg: true, }, @@ -1349,13 +1351,13 @@ }, { name: "dominant-baseline", - property_class: "Inherited", + property_class: true, inherited: true, svg: true, }, { name: "empty-cells", - property_class: "Inherited", + property_class: true, independent: true, inherited: true, field_template: "keyword", @@ -1383,7 +1385,7 @@ }, { name: "fill-rule", - property_class: "Inherited", + property_class: true, inherited: true, svg: true, type_name: "WindRule", @@ -1415,6 +1417,7 @@ }, { name: "flex-direction", + property_class: true, field_group: "*", field_template: "keyword", keywords: ["row", "row-reverse", "column", "column-reverse"], @@ -1442,6 +1445,7 @@ }, { name: "flex-wrap", + property_class: true, field_group: "*", field_template: "keyword", keywords: ["nowrap", "wrap", "wrap-reverse"], @@ -1620,7 +1624,7 @@ }, { name: "image-rendering", - property_class: "Inherited", + property_class: true, inherited: true, field_group: "*", field_template: "keyword", @@ -1754,7 +1758,7 @@ }, { name: "list-style-position", - property_class: "Inherited", + property_class: true, independent: true, inherited: true, field_template: "keyword", @@ -1763,7 +1767,7 @@ }, { name: "list-style-type", - property_class: "Inherited", + property_class: true, inherited: true, field_template: "keyword", keywords: [ @@ -2105,7 +2109,7 @@ }, { name: "overflow-wrap", - property_class: "Inherited", + property_class: true, inherited: true, field_group: "*", field_template: "keyword", @@ -2205,7 +2209,7 @@ }, { name: "pointer-events", - property_class: "Inherited", + property_class: true, independent: true, inherited: true, field_template: "keyword", @@ -2566,7 +2570,7 @@ }, { name: "shape-rendering", - property_class: "Inherited", + property_class: true, inherited: true, svg: true, }, @@ -2578,7 +2582,7 @@ }, { name: "speak", - property_class: "Inherited", + property_class: true, inherited: true, field_group: "*", field_template: "keyword", @@ -2636,7 +2640,7 @@ }, { name: "stroke-linecap", - property_class: "Inherited", + property_class: true, inherited: true, svg: true, name_for_methods: "CapStyle", @@ -2644,7 +2648,7 @@ }, { name: "stroke-linejoin", - property_class: "Inherited", + property_class: true, inherited: true, svg: true, name_for_methods: "JoinStyle", @@ -2701,7 +2705,7 @@ }, { name: "text-align", - property_class: "Inherited", + property_class: true, independent: false, inherited: true, field_template: "keyword", @@ -2715,7 +2719,7 @@ }, { name: "text-align-last", - property_class: "Inherited", + property_class: true, inherited: true, field_group: "*", field_template: "keyword", @@ -2724,13 +2728,13 @@ }, { name: "text-anchor", - property_class: "Inherited", + property_class: true, inherited: true, svg: true, }, { name: "text-combine-upright", - property_class: "Inherited", + property_class: true, inherited: true, field_group: "*", field_template: "keyword", @@ -2839,7 +2843,7 @@ }, { name: "text-transform", - property_class: "Inherited", + property_class: true, independent: true, inherited: true, field_template: "keyword", @@ -2920,6 +2924,7 @@ }, { name: "transform-style", + property_class: true, field_group: "*", field_template: "keyword", keywords: ["flat", "preserve-3d"], @@ -3090,7 +3095,7 @@ }, { name: "-webkit-box-direction", - property_class: "Inherited", + property_class: true, independent: true, inherited: true, field_template: "keyword", @@ -3198,6 +3203,7 @@ }, { name: "column-rule-style", + property_class: true, field_group: "*", field_template: "keyword", keywords: [ @@ -3270,7 +3276,7 @@ }, { name: "-webkit-line-break", - property_class: "Inherited", + property_class: true, inherited: true, field_group: "*", field_template: "keyword", @@ -3280,7 +3286,7 @@ }, { name: "line-break", - property_class: "Inherited", + property_class: true, inherited: true, type_name: "LineBreak", }, @@ -3425,7 +3431,7 @@ }, { name: "-webkit-print-color-adjust", - property_class: "Inherited", + property_class: true, independent: true, inherited: true, field_template: "keyword", @@ -3434,7 +3440,7 @@ }, { name: "-webkit-rtl-ordering", - property_class: "Inherited", + property_class: true, independent: true, inherited: true, field_template: "keyword", @@ -3446,7 +3452,7 @@ }, { name: "-webkit-ruby-position", - property_class: "Inherited", + property_class: true, inherited: true, field_group: "*", field_template: "keyword", @@ -3466,7 +3472,7 @@ }, { name: "-webkit-text-combine", - property_class: "Inherited", + property_class: true, inherited: true, name_for_methods: "TextCombine", }, @@ -3517,7 +3523,7 @@ }, { name: "-webkit-text-security", - property_class: "Inherited", + property_class: true, inherited: true, field_group: "*", field_template: "keyword", @@ -3579,7 +3585,7 @@ }, { name: "-webkit-user-modify", - property_class: "Inherited", + property_class: true, inherited: true, field_group: "*", field_template: "keyword", @@ -3588,7 +3594,7 @@ }, { name: "user-select", - property_class: "Inherited", + property_class: true, inherited: true, field_group: "*", field_template: "keyword", @@ -3597,7 +3603,7 @@ }, { name: "white-space", - property_class: "Inherited", + property_class: true, independent: true, inherited: true, field_template: "keyword", @@ -3638,7 +3644,7 @@ }, { name: "word-break", - property_class: "Inherited", + property_class: true, inherited: true, field_group: "*", field_template: "keyword", @@ -3658,7 +3664,7 @@ // property. So using the same handlers. { name: "word-wrap", - property_class: "Inherited", + property_class: true, inherited: true, name_for_methods: "OverflowWrap", }, @@ -4535,284 +4541,353 @@ // Aliases; these map to the same CSSPropertyID { name: "-epub-caption-side", + property_class: true, alias_for: "caption-side", }, { name: "-epub-text-combine", + property_class: true, alias_for: "-webkit-text-combine", }, { name: "-epub-text-emphasis", + property_class: true, alias_for: "-webkit-text-emphasis", }, { name: "-epub-text-emphasis-color", + property_class: true, alias_for: "-webkit-text-emphasis-color", }, { name: "-epub-text-emphasis-style", + property_class: true, alias_for: "-webkit-text-emphasis-style", }, { name: "-epub-text-orientation", + property_class: true, alias_for: "-webkit-text-orientation", }, { name: "-epub-text-transform", + property_class: true, alias_for: "text-transform", }, { name: "-epub-word-break", + property_class: true, alias_for: "word-break", }, { name: "-epub-writing-mode", + property_class: true, alias_for: "-webkit-writing-mode", }, { name: "-webkit-align-content", + property_class: true, alias_for: "align-content", }, { name: "-webkit-align-items", + property_class: true, alias_for: "align-items", }, { name: "-webkit-align-self", + property_class: true, alias_for: "align-self", }, { name: "-webkit-animation", + property_class: true, alias_for: "animation", }, { name: "-webkit-animation-delay", + property_class: true, alias_for: "animation-delay", }, { name: "-webkit-animation-direction", + property_class: true, alias_for: "animation-direction", }, { name: "-webkit-animation-duration", + property_class: true, alias_for: "animation-duration", }, { name: "-webkit-animation-fill-mode", + property_class: true, alias_for: "animation-fill-mode", }, { name: "-webkit-animation-iteration-count", + property_class: true, alias_for: "animation-iteration-count", }, { name: "-webkit-animation-name", + property_class: true, alias_for: "animation-name", }, { name: "-webkit-animation-play-state", + property_class: true, alias_for: "animation-play-state", }, { name: "-webkit-animation-timing-function", + property_class: true, alias_for: "animation-timing-function", }, { name: "-webkit-backface-visibility", + property_class: true, alias_for: "backface-visibility", }, // -webkit-background-clip accepts "content", "padding", and "border" values // See crbug.com/604023 { name: "-webkit-background-clip", + property_class: true, alias_for: "background-clip", }, // -webkit-background-origin accepts "content", "padding", and "border" // values. See crbug.com/604023 { name: "-webkit-background-origin", + property_class: true, alias_for: "background-origin" }, // "-webkit-background-size: 10px" behaves as "background-size: 10px 10px" { name: "-webkit-background-size", + property_class: true, alias_for: "background-size", }, { name: "-webkit-border-bottom-left-radius", + property_class: true, alias_for: "border-bottom-left-radius", }, { name: "-webkit-border-bottom-right-radius", + property_class: true, alias_for: "border-bottom-right-radius", }, // "-webkit-border-radius: 1px 2px" behaves as "border-radius: 1px / 2px" { name: "-webkit-border-radius", + property_class: true, alias_for: "border-radius", }, { name: "-webkit-border-top-left-radius", + property_class: true, alias_for: "border-top-left-radius", }, { name: "-webkit-border-top-right-radius", + property_class: true, alias_for: "border-top-right-radius", }, { name: "-webkit-box-shadow", + property_class: true, alias_for: "box-shadow", }, { name: "-webkit-box-sizing", + property_class: true, alias_for: "box-sizing", }, { name: "-webkit-clip-path", + property_class: true, alias_for: "clip-path", }, { name: "-webkit-column-count", + property_class: true, alias_for: "column-count", }, { name: "-webkit-column-gap", + property_class: true, alias_for: "column-gap", }, { name: "-webkit-column-rule", + property_class: true, alias_for: "column-rule", }, { name: "-webkit-column-rule-color", + property_class: true, alias_for: "column-rule-color", }, { name: "-webkit-column-rule-style", + property_class: true, alias_for: "column-rule-style", }, { name: "-webkit-column-rule-width", + property_class: true, alias_for: "column-rule-width", }, { name: "-webkit-column-span", + property_class: true, alias_for: "column-span", }, { name: "-webkit-column-width", + property_class: true, alias_for: "column-width", }, { name: "-webkit-columns", + property_class: true, alias_for: "columns", }, { name: "-webkit-filter", + property_class: true, alias_for: "filter", }, { name: "-webkit-flex", + property_class: true, alias_for: "flex", }, { name: "-webkit-flex-basis", + property_class: true, alias_for: "flex-basis", }, { name: "-webkit-flex-direction", + property_class: true, alias_for: "flex-direction", }, { name: "-webkit-flex-flow", + property_class: true, alias_for: "flex-flow", }, { name: "-webkit-flex-grow", + property_class: true, alias_for: "flex-grow", }, { name: "-webkit-flex-shrink", + property_class: true, alias_for: "flex-shrink", }, { name: "-webkit-flex-wrap", + property_class: true, alias_for: "flex-wrap", }, { name: "-webkit-font-feature-settings", + property_class: true, alias_for: "font-feature-settings", }, { name: "-webkit-justify-content", + property_class: true, alias_for: "justify-content", }, { name: "-webkit-opacity", + property_class: true, alias_for: "opacity", }, { name: "-webkit-order", + property_class: true, alias_for: "order", }, { name: "-webkit-perspective", + property_class: true, alias_for: "perspective", }, { name: "-webkit-perspective-origin", + property_class: true, alias_for: "perspective-origin", }, { name: "-webkit-shape-image-threshold", + property_class: true, alias_for: "shape-image-threshold", }, { name: "-webkit-shape-margin", + property_class: true, alias_for: "shape-margin", }, { name: "-webkit-shape-outside", + property_class: true, alias_for: "shape-outside", }, { name: "-webkit-text-size-adjust", + property_class: true, alias_for: "text-size-adjust", }, { name: "-webkit-transform", + property_class: true, alias_for: "transform", }, { name: "-webkit-transform-origin", + property_class: true, alias_for: "transform-origin", }, { name: "-webkit-transform-style", + property_class: true, alias_for: "transform-style", }, { name: "-webkit-transition", + property_class: true, alias_for: "transition", }, { name: "-webkit-transition-delay", + property_class: true, alias_for: "transition-delay", }, { name: "-webkit-transition-duration", + property_class: true, alias_for: "transition-duration", }, { name: "-webkit-transition-property", + property_class: true, alias_for: "transition-property", }, { name: "-webkit-transition-timing-function", + property_class: true, alias_for: "transition-timing-function", }, { name: "-webkit-user-select", + property_class: true, alias_for: "user-select", }, ],
diff --git a/third_party/WebKit/Source/core/css/CSSPropertyValueSet.cpp b/third_party/WebKit/Source/core/css/CSSPropertyValueSet.cpp index 15e78c1..25b21e64 100644 --- a/third_party/WebKit/Source/core/css/CSSPropertyValueSet.cpp +++ b/third_party/WebKit/Source/core/css/CSSPropertyValueSet.cpp
@@ -26,10 +26,13 @@ #include "core/StylePropertyShorthand.h" #include "core/css/CSSCustomPropertyDeclaration.h" #include "core/css/CSSIdentifierValue.h" -#include "core/css/ImmutableCSSPropertyValueSet.h" -#include "core/css/MutableCSSPropertyValueSet.h" #include "core/css/StylePropertySerializer.h" +#include "core/css/StyleSheetContents.h" +#include "core/css/parser/CSSParser.h" +#include "core/css/parser/CSSParserContext.h" #include "core/css/properties/CSSProperty.h" +#include "core/frame/UseCounter.h" +#include "platform/wtf/text/StringBuilder.h" #ifndef NDEBUG #include <stdio.h> @@ -38,27 +41,170 @@ namespace blink { -namespace { +static size_t SizeForImmutableCSSPropertyValueSetWithPropertyCount( + unsigned count) { + return sizeof(ImmutableCSSPropertyValueSet) - sizeof(void*) + + sizeof(Member<CSSValue>) * count + + sizeof(CSSPropertyValueMetadata) * count; +} -String SerializeShorthand(const CSSPropertyValueSet& property_set, - CSSPropertyID property_id) { +ImmutableCSSPropertyValueSet* ImmutableCSSPropertyValueSet::Create( + const CSSPropertyValue* properties, + unsigned count, + CSSParserMode css_parser_mode) { + DCHECK_LE(count, static_cast<unsigned>(kMaxArraySize)); + void* slot = ThreadHeap::Allocate<CSSPropertyValueSet>( + SizeForImmutableCSSPropertyValueSetWithPropertyCount(count)); + return new (slot) + ImmutableCSSPropertyValueSet(properties, count, css_parser_mode); +} + +ImmutableCSSPropertyValueSet* CSSPropertyValueSet::ImmutableCopyIfNeeded() + const { + if (!IsMutable()) { + return ToImmutableCSSPropertyValueSet( + const_cast<CSSPropertyValueSet*>(this)); + } + const MutableCSSPropertyValueSet* mutable_this = + ToMutableCSSPropertyValueSet(this); + return ImmutableCSSPropertyValueSet::Create( + mutable_this->property_vector_.data(), + mutable_this->property_vector_.size(), CssParserMode()); +} + +MutableCSSPropertyValueSet::MutableCSSPropertyValueSet( + CSSParserMode css_parser_mode) + : CSSPropertyValueSet(css_parser_mode) {} + +MutableCSSPropertyValueSet::MutableCSSPropertyValueSet( + const CSSPropertyValue* properties, + unsigned length) + : CSSPropertyValueSet(kHTMLStandardMode) { + property_vector_.ReserveInitialCapacity(length); + for (unsigned i = 0; i < length; ++i) + property_vector_.UncheckedAppend(properties[i]); +} + +ImmutableCSSPropertyValueSet::ImmutableCSSPropertyValueSet( + const CSSPropertyValue* properties, + unsigned length, + CSSParserMode css_parser_mode) + : CSSPropertyValueSet(css_parser_mode, length) { + CSSPropertyValueMetadata* metadata_array = + const_cast<CSSPropertyValueMetadata*>(this->MetadataArray()); + Member<const CSSValue>* value_array = + const_cast<Member<const CSSValue>*>(this->ValueArray()); + for (unsigned i = 0; i < array_size_; ++i) { + metadata_array[i] = properties[i].Metadata(); + value_array[i] = properties[i].Value(); + } +} + +ImmutableCSSPropertyValueSet::~ImmutableCSSPropertyValueSet() = default; + +// Convert property into an uint16_t for comparison with metadata's property id +// to avoid the compiler converting it to an int multiple times in a loop. +static uint16_t GetConvertedCSSPropertyID(CSSPropertyID property_id) { + return static_cast<uint16_t>(property_id); +} + +static uint16_t GetConvertedCSSPropertyID(const AtomicString&) { + return static_cast<uint16_t>(CSSPropertyVariable); +} + +static uint16_t GetConvertedCSSPropertyID(AtRuleDescriptorID descriptor_id) { + return static_cast<uint16_t>( + AtRuleDescriptorIDAsCSSPropertyID(descriptor_id)); +} + +static bool IsPropertyMatch(const CSSPropertyValueMetadata& metadata, + const CSSValue&, + uint16_t id, + CSSPropertyID property_id) { + DCHECK_EQ(id, property_id); + bool result = metadata.Property().PropertyID() == id; +// Only enabled properties should be part of the style. +#if DCHECK_IS_ON() + DCHECK(!result || + CSSProperty::Get(resolveCSSPropertyID(property_id)).IsEnabled()); +#endif + return result; +} + +static bool IsPropertyMatch(const CSSPropertyValueMetadata& metadata, + const CSSValue& value, + uint16_t id, + const AtomicString& custom_property_name) { + DCHECK_EQ(id, CSSPropertyVariable); + return metadata.Property().PropertyID() == id && + ToCSSCustomPropertyDeclaration(value).GetName() == + custom_property_name; +} + +static bool IsPropertyMatch(const CSSPropertyValueMetadata& metadata, + const CSSValue& css_value, + uint16_t id, + AtRuleDescriptorID descriptor_id) { + return IsPropertyMatch(metadata, css_value, id, + AtRuleDescriptorIDAsCSSPropertyID(descriptor_id)); +} + +template <typename T> +int ImmutableCSSPropertyValueSet::FindPropertyIndex(T property) const { + uint16_t id = GetConvertedCSSPropertyID(property); + for (int n = array_size_ - 1; n >= 0; --n) { + if (IsPropertyMatch(MetadataArray()[n], *ValueArray()[n], id, property)) + return n; + } + + return -1; +} +template CORE_EXPORT int ImmutableCSSPropertyValueSet::FindPropertyIndex( + CSSPropertyID) const; +template CORE_EXPORT int ImmutableCSSPropertyValueSet::FindPropertyIndex( + AtomicString) const; +template CORE_EXPORT int ImmutableCSSPropertyValueSet::FindPropertyIndex( + AtRuleDescriptorID) const; + +void ImmutableCSSPropertyValueSet::TraceAfterDispatch(blink::Visitor* visitor) { + const Member<const CSSValue>* values = ValueArray(); + for (unsigned i = 0; i < array_size_; i++) + visitor->Trace(values[i]); + CSSPropertyValueSet::TraceAfterDispatch(visitor); +} + +MutableCSSPropertyValueSet::MutableCSSPropertyValueSet( + const CSSPropertyValueSet& other) + : CSSPropertyValueSet(other.CssParserMode()) { + if (other.IsMutable()) { + property_vector_ = ToMutableCSSPropertyValueSet(other).property_vector_; + } else { + property_vector_.ReserveInitialCapacity(other.PropertyCount()); + for (unsigned i = 0; i < other.PropertyCount(); ++i) { + property_vector_.UncheckedAppend( + other.PropertyAt(i).ToCSSPropertyValue()); + } + } +} + +static String SerializeShorthand(const CSSPropertyValueSet& property_set, + CSSPropertyID property_id) { return StylePropertySerializer(property_set).GetPropertyValue(property_id); } -String SerializeShorthand(const CSSPropertyValueSet&, - const AtomicString& custom_property_name) { +static String SerializeShorthand(const CSSPropertyValueSet&, + const AtomicString& custom_property_name) { // Custom properties are never shorthands. return ""; } -String SerializeShorthand(const CSSPropertyValueSet& property_set, - AtRuleDescriptorID atrule_id) { +static String SerializeShorthand(const CSSPropertyValueSet& property_set, + AtRuleDescriptorID atrule_id) { return StylePropertySerializer(property_set) .GetPropertyValue(AtRuleDescriptorIDAsCSSPropertyID(atrule_id)); + ; } -} // namespace - template <typename T> String CSSPropertyValueSet::GetPropertyValue(T property) const { const CSSValue* value = GetPropertyCSSValue(property); @@ -102,6 +248,53 @@ ToImmutableCSSPropertyValueSet(this)->~ImmutableCSSPropertyValueSet(); } +bool MutableCSSPropertyValueSet::RemoveShorthandProperty( + CSSPropertyID property_id) { + StylePropertyShorthand shorthand = shorthandForProperty(property_id); + if (!shorthand.length()) + return false; + + return RemovePropertiesInSet(shorthand.properties(), shorthand.length()); +} + +bool MutableCSSPropertyValueSet::RemovePropertyAtIndex(int property_index, + String* return_text) { + if (property_index == -1) { + if (return_text) + *return_text = ""; + return false; + } + + if (return_text) + *return_text = PropertyAt(property_index).Value().CssText(); + + // A more efficient removal strategy would involve marking entries as empty + // and sweeping them when the vector grows too big. + property_vector_.EraseAt(property_index); + + return true; +} + +template <typename T> +bool MutableCSSPropertyValueSet::RemoveProperty(T property, + String* return_text) { + if (RemoveShorthandProperty(property)) { + // FIXME: Return an equivalent shorthand when possible. + if (return_text) + *return_text = ""; + return true; + } + + int found_property_index = FindPropertyIndex(property); + return RemovePropertyAtIndex(found_property_index, return_text); +} +template CORE_EXPORT bool MutableCSSPropertyValueSet::RemoveProperty( + CSSPropertyID, + String*); +template CORE_EXPORT bool MutableCSSPropertyValueSet::RemoveProperty( + AtomicString, + String*); + template <typename T> bool CSSPropertyValueSet::PropertyIsImportant(T property) const { int found_property_index = FindPropertyIndex(property); @@ -148,10 +341,246 @@ return PropertyAt(found_property_index).IsImplicit(); } +MutableCSSPropertyValueSet::SetResult MutableCSSPropertyValueSet::SetProperty( + CSSPropertyID unresolved_property, + const String& value, + bool important, + SecureContextMode secure_context_mode, + StyleSheetContents* context_style_sheet) { + DCHECK_GE(unresolved_property, firstCSSProperty); + + // Setting the value to an empty string just removes the property in both IE + // and Gecko. Setting it to null seems to produce less consistent results, but + // we treat it just the same. + if (value.IsEmpty()) { + bool did_parse = true; + bool did_change = RemoveProperty(resolveCSSPropertyID(unresolved_property)); + return SetResult{did_parse, did_change}; + } + + // When replacing an existing property value, this moves the property to the + // end of the list. Firefox preserves the position, and MSIE moves the + // property to the beginning. + return CSSParser::ParseValue(this, unresolved_property, value, important, + secure_context_mode, context_style_sheet); +} + +MutableCSSPropertyValueSet::SetResult MutableCSSPropertyValueSet::SetProperty( + const AtomicString& custom_property_name, + const PropertyRegistry* registry, + const String& value, + bool important, + SecureContextMode secure_context_mode, + StyleSheetContents* context_style_sheet, + bool is_animation_tainted) { + if (value.IsEmpty()) { + bool did_parse = true; + bool did_change = RemoveProperty(custom_property_name); + return MutableCSSPropertyValueSet::SetResult{did_parse, did_change}; + } + return CSSParser::ParseValueForCustomProperty( + this, custom_property_name, registry, value, important, + secure_context_mode, context_style_sheet, is_animation_tainted); +} + +void MutableCSSPropertyValueSet::SetProperty(CSSPropertyID property_id, + const CSSValue& value, + bool important) { + StylePropertyShorthand shorthand = shorthandForProperty(property_id); + if (!shorthand.length()) { + SetProperty( + CSSPropertyValue(CSSProperty::Get(property_id), value, important)); + return; + } + + RemovePropertiesInSet(shorthand.properties(), shorthand.length()); + + for (unsigned i = 0; i < shorthand.length(); ++i) { + property_vector_.push_back( + CSSPropertyValue(*shorthand.properties()[i], value, important)); + } +} + +bool MutableCSSPropertyValueSet::SetProperty(const CSSPropertyValue& property, + CSSPropertyValue* slot) { + const AtomicString& name = + (property.Id() == CSSPropertyVariable) + ? ToCSSCustomPropertyDeclaration(property.Value())->GetName() + : g_null_atom; + CSSPropertyValue* to_replace = + slot ? slot : FindCSSPropertyWithID(property.Id(), name); + if (to_replace && *to_replace == property) + return false; + if (to_replace) { + *to_replace = property; + return true; + } + property_vector_.push_back(property); + return true; +} + +bool MutableCSSPropertyValueSet::SetProperty(CSSPropertyID property_id, + CSSValueID identifier, + bool important) { + SetProperty(CSSPropertyValue(CSSProperty::Get(property_id), + *CSSIdentifierValue::Create(identifier), + important)); + return true; +} + +void MutableCSSPropertyValueSet::ParseDeclarationList( + const String& style_declaration, + SecureContextMode secure_context_mode, + StyleSheetContents* context_style_sheet) { + property_vector_.clear(); + + CSSParserContext* context; + if (context_style_sheet) { + context = CSSParserContext::CreateWithStyleSheetContents( + context_style_sheet->ParserContext(), context_style_sheet); + context->SetMode(CssParserMode()); + } else { + context = CSSParserContext::Create(CssParserMode(), secure_context_mode); + } + + CSSParser::ParseDeclarationList(context, this, style_declaration); +} + +bool MutableCSSPropertyValueSet::AddParsedProperties( + const HeapVector<CSSPropertyValue, 256>& properties) { + bool changed = false; + property_vector_.ReserveCapacity(property_vector_.size() + properties.size()); + for (unsigned i = 0; i < properties.size(); ++i) + changed |= SetProperty(properties[i]); + return changed; +} + +bool MutableCSSPropertyValueSet::AddRespectingCascade( + const CSSPropertyValue& property) { + // Only add properties that have no !important counterpart present + if (!PropertyIsImportant(property.Id()) || property.IsImportant()) + return SetProperty(property); + return false; +} + String CSSPropertyValueSet::AsText() const { return StylePropertySerializer(*this).AsText(); } +void MutableCSSPropertyValueSet::MergeAndOverrideOnConflict( + const CSSPropertyValueSet* other) { + unsigned size = other->PropertyCount(); + for (unsigned n = 0; n < size; ++n) { + PropertyReference to_merge = other->PropertyAt(n); + // TODO(leviw): This probably doesn't work correctly with Custom Properties + CSSPropertyValue* old = FindCSSPropertyWithID(to_merge.Id()); + if (old) + SetProperty(to_merge.ToCSSPropertyValue(), old); + else + property_vector_.push_back(to_merge.ToCSSPropertyValue()); + } +} + +bool CSSPropertyValueSet::HasFailedOrCanceledSubresources() const { + unsigned size = PropertyCount(); + for (unsigned i = 0; i < size; ++i) { + if (PropertyAt(i).Value().HasFailedOrCanceledSubresources()) + return true; + } + return false; +} + +void MutableCSSPropertyValueSet::Clear() { + property_vector_.clear(); +} + +inline bool ContainsId(const CSSProperty** set, + unsigned length, + CSSPropertyID id) { + for (unsigned i = 0; i < length; ++i) { + if (set[i]->IDEquals(id)) + return true; + } + return false; +} + +bool MutableCSSPropertyValueSet::RemovePropertiesInSet(const CSSProperty** set, + unsigned length) { + if (property_vector_.IsEmpty()) + return false; + + CSSPropertyValue* properties = property_vector_.data(); + unsigned old_size = property_vector_.size(); + unsigned new_index = 0; + for (unsigned old_index = 0; old_index < old_size; ++old_index) { + const CSSPropertyValue& property = properties[old_index]; + if (ContainsId(set, length, property.Id())) + continue; + // Modify property_vector_ in-place since this method is + // performance-sensitive. + properties[new_index++] = properties[old_index]; + } + if (new_index != old_size) { + property_vector_.Shrink(new_index); + return true; + } + return false; +} + +CSSPropertyValue* MutableCSSPropertyValueSet::FindCSSPropertyWithID( + CSSPropertyID property_id, + const AtomicString& custom_property_name) { + int found_property_index = -1; + if (property_id == CSSPropertyVariable && !custom_property_name.IsNull()) { + // TODO(shanestephens): fix call sites so we always have a + // customPropertyName here. + found_property_index = FindPropertyIndex(custom_property_name); + } else { + DCHECK(custom_property_name.IsNull()); + found_property_index = FindPropertyIndex(property_id); + } + if (found_property_index == -1) + return nullptr; + return &property_vector_.at(found_property_index); +} + +bool CSSPropertyValueSet::PropertyMatches( + CSSPropertyID property_id, + const CSSValue& property_value) const { + int found_property_index = FindPropertyIndex(property_id); + if (found_property_index == -1) + return false; + return PropertyAt(found_property_index).Value() == property_value; +} + +void MutableCSSPropertyValueSet::RemoveEquivalentProperties( + const CSSPropertyValueSet* style) { + Vector<CSSPropertyID> properties_to_remove; + unsigned size = property_vector_.size(); + for (unsigned i = 0; i < size; ++i) { + PropertyReference property = PropertyAt(i); + if (style->PropertyMatches(property.Id(), property.Value())) + properties_to_remove.push_back(property.Id()); + } + // FIXME: This should use mass removal. + for (unsigned i = 0; i < properties_to_remove.size(); ++i) + RemoveProperty(properties_to_remove[i]); +} + +void MutableCSSPropertyValueSet::RemoveEquivalentProperties( + const CSSStyleDeclaration* style) { + Vector<CSSPropertyID> properties_to_remove; + unsigned size = property_vector_.size(); + for (unsigned i = 0; i < size; ++i) { + PropertyReference property = PropertyAt(i); + if (style->CssPropertyMatches(property.Id(), &property.Value())) + properties_to_remove.push_back(property.Id()); + } + // FIXME: This should use mass removal. + for (unsigned i = 0; i < properties_to_remove.size(); ++i) + RemoveProperty(properties_to_remove[i]); +} + MutableCSSPropertyValueSet* CSSPropertyValueSet::MutableCopy() const { return new MutableCSSPropertyValueSet(*this); } @@ -169,10 +598,49 @@ return MutableCSSPropertyValueSet::Create(list.data(), list.size()); } +CSSStyleDeclaration* MutableCSSPropertyValueSet::EnsureCSSStyleDeclaration() { + // FIXME: get rid of this weirdness of a CSSStyleDeclaration inside of a + // style property set. + if (cssom_wrapper_) { + DCHECK( + !static_cast<CSSStyleDeclaration*>(cssom_wrapper_.Get())->parentRule()); + DCHECK(!cssom_wrapper_->ParentElement()); + return cssom_wrapper_.Get(); + } + cssom_wrapper_ = new PropertySetCSSStyleDeclaration(*this); + return cssom_wrapper_.Get(); +} + +template <typename T> +int MutableCSSPropertyValueSet::FindPropertyIndex(T property) const { + const CSSPropertyValue* begin = property_vector_.data(); + const CSSPropertyValue* end = begin + property_vector_.size(); + + uint16_t id = GetConvertedCSSPropertyID(property); + + const CSSPropertyValue* it = std::find_if( + begin, end, [property, id](const CSSPropertyValue& css_property) -> bool { + return IsPropertyMatch(css_property.Metadata(), *css_property.Value(), + id, property); + }); + + return (it == end) ? -1 : it - begin; +} +template CORE_EXPORT int MutableCSSPropertyValueSet::FindPropertyIndex( + CSSPropertyID) const; +template CORE_EXPORT int MutableCSSPropertyValueSet::FindPropertyIndex( + AtomicString) const; + +void MutableCSSPropertyValueSet::TraceAfterDispatch(blink::Visitor* visitor) { + visitor->Trace(cssom_wrapper_); + visitor->Trace(property_vector_); + CSSPropertyValueSet::TraceAfterDispatch(visitor); +} + unsigned CSSPropertyValueSet::AverageSizeInBytes() { // Please update this if the storage scheme changes so that this longer // reflects the actual size. - return ImmutableCSSPropertyValueSet::SizeWithPropertyCount(4); + return SizeForImmutableCSSPropertyValueSetWithPropertyCount(4); } // See the function above if you need to update this. @@ -190,107 +658,17 @@ } #endif -const CSSPropertyValueMetadata& -CSSPropertyValueSet::PropertyReference::PropertyMetadata() const { - if (property_set_->IsMutable()) { - return ToMutableCSSPropertyValueSet(*property_set_) - .property_vector_.at(index_) - .Metadata(); - } - return ToImmutableCSSPropertyValueSet(*property_set_).MetadataArray()[index_]; +MutableCSSPropertyValueSet* MutableCSSPropertyValueSet::Create( + CSSParserMode css_parser_mode) { + return new MutableCSSPropertyValueSet(css_parser_mode); } -const CSSValue& CSSPropertyValueSet::PropertyReference::PropertyValue() const { - if (property_set_->IsMutable()) { - return *ToMutableCSSPropertyValueSet(*property_set_) - .property_vector_.at(index_) - .Value(); - } - return *ToImmutableCSSPropertyValueSet(*property_set_).ValueArray()[index_]; +MutableCSSPropertyValueSet* MutableCSSPropertyValueSet::Create( + const CSSPropertyValue* properties, + unsigned count) { + return new MutableCSSPropertyValueSet(properties, count); } -unsigned CSSPropertyValueSet::PropertyCount() const { - if (is_mutable_) - return ToMutableCSSPropertyValueSet(this)->property_vector_.size(); - return array_size_; -} - -bool CSSPropertyValueSet::IsEmpty() const { - return !PropertyCount(); -} - -template <typename T> -int CSSPropertyValueSet::FindPropertyIndex(T property) const { - if (is_mutable_) - return ToMutableCSSPropertyValueSet(this)->FindPropertyIndex(property); - return ToImmutableCSSPropertyValueSet(this)->FindPropertyIndex(property); -} -template CORE_EXPORT int CSSPropertyValueSet::FindPropertyIndex( - CSSPropertyID) const; -template CORE_EXPORT int CSSPropertyValueSet::FindPropertyIndex( - AtomicString) const; -template CORE_EXPORT int CSSPropertyValueSet::FindPropertyIndex( - AtRuleDescriptorID) const; - -// Convert property into an uint16_t for comparison with metadata's property id -// to avoid the compiler converting it to an int multiple times in a loop. -uint16_t CSSPropertyValueSet::GetConvertedCSSPropertyID( - CSSPropertyID property_id) { - return static_cast<uint16_t>(property_id); -} - -uint16_t CSSPropertyValueSet::GetConvertedCSSPropertyID(const AtomicString&) { - return static_cast<uint16_t>(CSSPropertyVariable); -} - -uint16_t CSSPropertyValueSet::GetConvertedCSSPropertyID( - AtRuleDescriptorID descriptor_id) { - return static_cast<uint16_t>( - AtRuleDescriptorIDAsCSSPropertyID(descriptor_id)); -} - -bool CSSPropertyValueSet::IsPropertyMatch( - const CSSPropertyValueMetadata& metadata, - const CSSValue&, - uint16_t id, - CSSPropertyID property_id) { - DCHECK_EQ(id, property_id); - bool result = metadata.Property().PropertyID() == id; -// Only enabled properties should be part of the style. -#if DCHECK_IS_ON() - DCHECK(!result || - CSSProperty::Get(resolveCSSPropertyID(property_id)).IsEnabled()); -#endif - return result; -} - -bool CSSPropertyValueSet::IsPropertyMatch( - const CSSPropertyValueMetadata& metadata, - const CSSValue& value, - uint16_t id, - const AtomicString& custom_property_name) { - DCHECK_EQ(id, CSSPropertyVariable); - return metadata.Property().PropertyID() == id && - ToCSSCustomPropertyDeclaration(value).GetName() == - custom_property_name; -} - -bool CSSPropertyValueSet::IsPropertyMatch( - const CSSPropertyValueMetadata& metadata, - const CSSValue& css_value, - uint16_t id, - AtRuleDescriptorID descriptor_id) { - return IsPropertyMatch(metadata, css_value, id, - AtRuleDescriptorIDAsCSSPropertyID(descriptor_id)); -} - -bool CSSPropertyValueSet::HasFailedOrCanceledSubresources() const { - unsigned size = PropertyCount(); - for (unsigned i = 0; i < size; ++i) { - if (PropertyAt(i).Value().HasFailedOrCanceledSubresources()) - return true; - } - return false; -} +void CSSLazyPropertyParser::Trace(blink::Visitor* visitor) {} } // namespace blink
diff --git a/third_party/WebKit/Source/core/css/CSSPropertyValueSet.h b/third_party/WebKit/Source/core/css/CSSPropertyValueSet.h index 42926ee..5a01dc07 100644 --- a/third_party/WebKit/Source/core/css/CSSPropertyValueSet.h +++ b/third_party/WebKit/Source/core/css/CSSPropertyValueSet.h
@@ -27,7 +27,6 @@ #include "core/css/CSSPrimitiveValue.h" #include "core/css/CSSPropertyValue.h" #include "core/css/PropertySetCSSStyleDeclaration.h" -#include "core/css/parser/AtRuleDescriptors.h" #include "core/css/parser/CSSParserMode.h" #include "platform/wtf/Noncopyable.h" #include "platform/wtf/Vector.h" @@ -35,8 +34,11 @@ namespace blink { +class CSSStyleDeclaration; class ImmutableCSSPropertyValueSet; class MutableCSSPropertyValueSet; +class PropertyRegistry; +class StyleSheetContents; enum class SecureContextMode; class CORE_EXPORT CSSPropertyValueSet @@ -90,20 +92,20 @@ return PropertyReference(*this, index); } - template <typename T> // CSSPropertyID, AtRuleDescriptorID or AtomicString + template <typename T> // CSSPropertyID or AtomicString int FindPropertyIndex(T property) const; bool HasProperty(CSSPropertyID property) const { return FindPropertyIndex(property) != -1; } - template <typename T> // CSSPropertyID, AtRuleDescriptorID or AtomicString + template <typename T> // CSSPropertyID or AtomicString const CSSValue* GetPropertyCSSValue(T property) const; - template <typename T> // CSSPropertyID, AtRuleDescriptorID or AtomicString + template <typename T> // CSSPropertyID or AtomicString String GetPropertyValue(T property) const; - template <typename T> // CSSPropertyID, AtRuleDescriptorID or AtomicString + template <typename T> // CSSPropertyID or AtomicString bool PropertyIsImportant(T property) const; bool ShorthandIsImportant(CSSPropertyID) const; @@ -156,22 +158,6 @@ array_size_ = unsigned(kMaxArraySize); } - static uint16_t GetConvertedCSSPropertyID(CSSPropertyID); - static uint16_t GetConvertedCSSPropertyID(const AtomicString&); - static uint16_t GetConvertedCSSPropertyID(AtRuleDescriptorID); - static bool IsPropertyMatch(const CSSPropertyValueMetadata&, - const CSSValue&, - uint16_t id, - CSSPropertyID); - static bool IsPropertyMatch(const CSSPropertyValueMetadata&, - const CSSValue&, - uint16_t id, - const AtomicString& custom_property_name); - static bool IsPropertyMatch(const CSSPropertyValueMetadata&, - const CSSValue&, - uint16_t id, - AtRuleDescriptorID); - unsigned css_parser_mode_ : 3; mutable unsigned is_mutable_ : 1; unsigned array_size_ : 28; @@ -180,6 +166,195 @@ DISALLOW_COPY_AND_ASSIGN(CSSPropertyValueSet); }; +// Used for lazily parsing properties. +class CSSLazyPropertyParser + : public GarbageCollectedFinalized<CSSLazyPropertyParser> { + public: + CSSLazyPropertyParser() = default; + virtual ~CSSLazyPropertyParser() = default; + virtual CSSPropertyValueSet* ParseProperties() = 0; + virtual void Trace(blink::Visitor*); + DISALLOW_COPY_AND_ASSIGN(CSSLazyPropertyParser); +}; + +class CORE_EXPORT ImmutableCSSPropertyValueSet : public CSSPropertyValueSet { + public: + ~ImmutableCSSPropertyValueSet(); + static ImmutableCSSPropertyValueSet* + Create(const CSSPropertyValue* properties, unsigned count, CSSParserMode); + + unsigned PropertyCount() const { return array_size_; } + + const Member<const CSSValue>* ValueArray() const; + const CSSPropertyValueMetadata* MetadataArray() const; + + template <typename T> // CSSPropertyID or AtomicString + int FindPropertyIndex(T property) const; + + void TraceAfterDispatch(blink::Visitor*); + + void* operator new(std::size_t, void* location) { return location; } + + void* storage_; + + private: + ImmutableCSSPropertyValueSet(const CSSPropertyValue*, + unsigned count, + CSSParserMode); +}; + +inline const Member<const CSSValue>* ImmutableCSSPropertyValueSet::ValueArray() + const { + return reinterpret_cast<const Member<const CSSValue>*>( + const_cast<const void**>(&(this->storage_))); +} + +inline const CSSPropertyValueMetadata* +ImmutableCSSPropertyValueSet::MetadataArray() const { + return reinterpret_cast<const CSSPropertyValueMetadata*>( + &reinterpret_cast<const char*>( + &(this->storage_))[array_size_ * sizeof(Member<CSSValue>)]); +} + +DEFINE_TYPE_CASTS(ImmutableCSSPropertyValueSet, + CSSPropertyValueSet, + set, + !set->IsMutable(), + !set.IsMutable()); + +class CORE_EXPORT MutableCSSPropertyValueSet : public CSSPropertyValueSet { + public: + ~MutableCSSPropertyValueSet() = default; + static MutableCSSPropertyValueSet* Create(CSSParserMode); + static MutableCSSPropertyValueSet* Create(const CSSPropertyValue* properties, + unsigned count); + + unsigned PropertyCount() const { return property_vector_.size(); } + + // Returns whether this style set was changed. + bool AddParsedProperties(const HeapVector<CSSPropertyValue, 256>&); + bool AddRespectingCascade(const CSSPropertyValue&); + + struct SetResult { + bool did_parse; + bool did_change; + }; + // These expand shorthand properties into multiple properties. + SetResult SetProperty(CSSPropertyID unresolved_property, + const String& value, + bool important, + SecureContextMode, + StyleSheetContents* context_style_sheet = nullptr); + SetResult SetProperty(const AtomicString& custom_property_name, + const PropertyRegistry*, + const String& value, + bool important, + SecureContextMode, + StyleSheetContents* context_style_sheet, + bool is_animation_tainted); + 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); + bool SetProperty(const CSSPropertyValue&, CSSPropertyValue* slot = nullptr); + + template <typename T> // CSSPropertyID or AtomicString + bool RemoveProperty(T property, String* return_text = nullptr); + bool RemovePropertiesInSet(const CSSProperty** set, unsigned length); + void RemoveEquivalentProperties(const CSSPropertyValueSet*); + void RemoveEquivalentProperties(const CSSStyleDeclaration*); + + void MergeAndOverrideOnConflict(const CSSPropertyValueSet*); + + void Clear(); + void ParseDeclarationList(const String& style_declaration, + SecureContextMode, + StyleSheetContents* context_style_sheet); + + CSSStyleDeclaration* EnsureCSSStyleDeclaration(); + + template <typename T> // CSSPropertyID or AtomicString + int FindPropertyIndex(T property) const; + + void TraceAfterDispatch(blink::Visitor*); + + private: + explicit MutableCSSPropertyValueSet(CSSParserMode); + explicit MutableCSSPropertyValueSet(const CSSPropertyValueSet&); + MutableCSSPropertyValueSet(const CSSPropertyValue* properties, + unsigned count); + + bool RemovePropertyAtIndex(int, String* return_text); + + bool RemoveShorthandProperty(CSSPropertyID); + bool RemoveShorthandProperty(const AtomicString& custom_property_name) { + return false; + } + CSSPropertyValue* FindCSSPropertyWithID( + CSSPropertyID, + const AtomicString& custom_property_name = g_null_atom); + Member<PropertySetCSSStyleDeclaration> cssom_wrapper_; + + friend class CSSPropertyValueSet; + + HeapVector<CSSPropertyValue, 4> property_vector_; +}; + +DEFINE_TYPE_CASTS(MutableCSSPropertyValueSet, + CSSPropertyValueSet, + set, + set->IsMutable(), + set.IsMutable()); + +inline MutableCSSPropertyValueSet* ToMutableCSSPropertyValueSet( + const Persistent<CSSPropertyValueSet>& set) { + return ToMutableCSSPropertyValueSet(set.Get()); +} + +inline MutableCSSPropertyValueSet* ToMutableCSSPropertyValueSet( + const Member<CSSPropertyValueSet>& set) { + return ToMutableCSSPropertyValueSet(set.Get()); +} + +inline const CSSPropertyValueMetadata& +CSSPropertyValueSet::PropertyReference::PropertyMetadata() const { + if (property_set_->IsMutable()) { + return ToMutableCSSPropertyValueSet(*property_set_) + .property_vector_.at(index_) + .Metadata(); + } + return ToImmutableCSSPropertyValueSet(*property_set_).MetadataArray()[index_]; +} + +inline const CSSValue& CSSPropertyValueSet::PropertyReference::PropertyValue() + const { + if (property_set_->IsMutable()) { + return *ToMutableCSSPropertyValueSet(*property_set_) + .property_vector_.at(index_) + .Value(); + } + return *ToImmutableCSSPropertyValueSet(*property_set_).ValueArray()[index_]; +} + +inline unsigned CSSPropertyValueSet::PropertyCount() const { + if (is_mutable_) + return ToMutableCSSPropertyValueSet(this)->property_vector_.size(); + return array_size_; +} + +inline bool CSSPropertyValueSet::IsEmpty() const { + return !PropertyCount(); +} + +template <typename T> +inline int CSSPropertyValueSet::FindPropertyIndex(T property) const { + if (is_mutable_) + return ToMutableCSSPropertyValueSet(this)->FindPropertyIndex(property); + return ToImmutableCSSPropertyValueSet(this)->FindPropertyIndex(property); +} + } // namespace blink #endif // CSSPropertyValueSet_h
diff --git a/third_party/WebKit/Source/core/css/CSSSelectorWatch.cpp b/third_party/WebKit/Source/core/css/CSSSelectorWatch.cpp index 7ad8193..54190eee 100644 --- a/third_party/WebKit/Source/core/css/CSSSelectorWatch.cpp +++ b/third_party/WebKit/Source/core/css/CSSSelectorWatch.cpp
@@ -30,7 +30,7 @@ #include "core/css/CSSSelectorWatch.h" -#include "core/css/ImmutableCSSPropertyValueSet.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/css/StyleEngine.h" #include "core/css/parser/CSSParser.h" #include "core/dom/Document.h"
diff --git a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp index 08358e99..b6a910e 100644 --- a/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp +++ b/third_party/WebKit/Source/core/css/ComputedStyleCSSValueMapping.cpp
@@ -1582,7 +1582,8 @@ DCHECK_EQ(property.property_type, CSSTransitionData::kTransitionKnownProperty); return CSSCustomIdentValue::Create( - getPropertyNameAtomicString(property.unresolved_property)); + CSSUnresolvedProperty::Get(property.unresolved_property) + .GetPropertyNameAtomicString()); } static CSSValue* ValueForTransitionProperty(
diff --git a/third_party/WebKit/Source/core/css/FontFaceCacheTest.cpp b/third_party/WebKit/Source/core/css/FontFaceCacheTest.cpp index 22d2761..f73dd1b 100644 --- a/third_party/WebKit/Source/core/css/FontFaceCacheTest.cpp +++ b/third_party/WebKit/Source/core/css/FontFaceCacheTest.cpp
@@ -6,11 +6,11 @@ #include "core/css/CSSFontFamilyValue.h" #include "core/css/CSSFontStyleRangeValue.h" #include "core/css/CSSIdentifierValue.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/css/CSSSegmentedFontFace.h" #include "core/css/CSSValueList.h" #include "core/css/FontFace.h" #include "core/css/FontFaceCache.h" -#include "core/css/MutableCSSPropertyValueSet.h" #include "core/css/StyleRule.h" #include "core/testing/PageTestBase.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/third_party/WebKit/Source/core/css/ImmutableCSSPropertyValueSet.cpp b/third_party/WebKit/Source/core/css/ImmutableCSSPropertyValueSet.cpp deleted file mode 100644 index 853d790..0000000 --- a/third_party/WebKit/Source/core/css/ImmutableCSSPropertyValueSet.cpp +++ /dev/null
@@ -1,81 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "core/css/ImmutableCSSPropertyValueSet.h" - -#include "core/css/MutableCSSPropertyValueSet.h" -#include "core/css/parser/AtRuleDescriptors.h" - -namespace blink { - -size_t ImmutableCSSPropertyValueSet::SizeWithPropertyCount(unsigned count) { - return sizeof(ImmutableCSSPropertyValueSet) - sizeof(void*) + - sizeof(Member<CSSValue>) * count + - sizeof(CSSPropertyValueMetadata) * count; -} - -ImmutableCSSPropertyValueSet* ImmutableCSSPropertyValueSet::Create( - const CSSPropertyValue* properties, - unsigned count, - CSSParserMode css_parser_mode) { - DCHECK_LE(count, static_cast<unsigned>(kMaxArraySize)); - void* slot = - ThreadHeap::Allocate<CSSPropertyValueSet>(SizeWithPropertyCount(count)); - return new (slot) - ImmutableCSSPropertyValueSet(properties, count, css_parser_mode); -} - -ImmutableCSSPropertyValueSet* CSSPropertyValueSet::ImmutableCopyIfNeeded() - const { - if (!IsMutable()) { - return ToImmutableCSSPropertyValueSet( - const_cast<CSSPropertyValueSet*>(this)); - } - const MutableCSSPropertyValueSet* mutable_this = - ToMutableCSSPropertyValueSet(this); - return ImmutableCSSPropertyValueSet::Create( - mutable_this->property_vector_.data(), - mutable_this->property_vector_.size(), CssParserMode()); -} - -ImmutableCSSPropertyValueSet::ImmutableCSSPropertyValueSet( - const CSSPropertyValue* properties, - unsigned length, - CSSParserMode css_parser_mode) - : CSSPropertyValueSet(css_parser_mode, length) { - CSSPropertyValueMetadata* metadata_array = - const_cast<CSSPropertyValueMetadata*>(this->MetadataArray()); - Member<const CSSValue>* value_array = - const_cast<Member<const CSSValue>*>(this->ValueArray()); - for (unsigned i = 0; i < array_size_; ++i) { - metadata_array[i] = properties[i].Metadata(); - value_array[i] = properties[i].Value(); - } -} - -template <typename T> -int ImmutableCSSPropertyValueSet::FindPropertyIndex(T property) const { - uint16_t id = GetConvertedCSSPropertyID(property); - for (int n = array_size_ - 1; n >= 0; --n) { - if (IsPropertyMatch(MetadataArray()[n], *ValueArray()[n], id, property)) - return n; - } - - return -1; -} -template CORE_EXPORT int ImmutableCSSPropertyValueSet::FindPropertyIndex( - CSSPropertyID) const; -template CORE_EXPORT int ImmutableCSSPropertyValueSet::FindPropertyIndex( - AtomicString) const; -template CORE_EXPORT int ImmutableCSSPropertyValueSet::FindPropertyIndex( - AtRuleDescriptorID) const; - -void ImmutableCSSPropertyValueSet::TraceAfterDispatch(blink::Visitor* visitor) { - const Member<const CSSValue>* values = ValueArray(); - for (unsigned i = 0; i < array_size_; i++) - visitor->Trace(values[i]); - CSSPropertyValueSet::TraceAfterDispatch(visitor); -} - -} // namespace blink
diff --git a/third_party/WebKit/Source/core/css/ImmutableCSSPropertyValueSet.h b/third_party/WebKit/Source/core/css/ImmutableCSSPropertyValueSet.h deleted file mode 100644 index 8c441890..0000000 --- a/third_party/WebKit/Source/core/css/ImmutableCSSPropertyValueSet.h +++ /dev/null
@@ -1,59 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ImmutableCSSPropertyValueSet_h -#define ImmutableCSSPropertyValueSet_h - -#include "core/css/CSSPropertyValueSet.h" - -namespace blink { - -class CORE_EXPORT ImmutableCSSPropertyValueSet : public CSSPropertyValueSet { - public: - static size_t SizeWithPropertyCount(unsigned count); - static ImmutableCSSPropertyValueSet* - Create(const CSSPropertyValue* properties, unsigned count, CSSParserMode); - - unsigned PropertyCount() const { return array_size_; } - - const Member<const CSSValue>* ValueArray() const; - const CSSPropertyValueMetadata* MetadataArray() const; - - template <typename T> // CSSPropertyID or AtomicString - int FindPropertyIndex(T property) const; - - void TraceAfterDispatch(blink::Visitor*); - - void* operator new(std::size_t, void* location) { return location; } - - void* storage_; - - private: - ImmutableCSSPropertyValueSet(const CSSPropertyValue*, - unsigned count, - CSSParserMode); -}; - -inline const Member<const CSSValue>* ImmutableCSSPropertyValueSet::ValueArray() - const { - return reinterpret_cast<const Member<const CSSValue>*>( - const_cast<const void**>(&(this->storage_))); -} - -inline const CSSPropertyValueMetadata* -ImmutableCSSPropertyValueSet::MetadataArray() const { - return reinterpret_cast<const CSSPropertyValueMetadata*>( - &reinterpret_cast<const char*>( - &(this->storage_))[array_size_ * sizeof(Member<CSSValue>)]); -} - -DEFINE_TYPE_CASTS(ImmutableCSSPropertyValueSet, - CSSPropertyValueSet, - set, - !set->IsMutable(), - !set.IsMutable()); - -} // namespace blink - -#endif // ImmutableCSSPropertyValueSet_h
diff --git a/third_party/WebKit/Source/core/css/MutableCSSPropertyValueSet.cpp b/third_party/WebKit/Source/core/css/MutableCSSPropertyValueSet.cpp deleted file mode 100644 index 183ae27..0000000 --- a/third_party/WebKit/Source/core/css/MutableCSSPropertyValueSet.cpp +++ /dev/null
@@ -1,373 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "core/css/MutableCSSPropertyValueSet.h" - -#include "core/StylePropertyShorthand.h" -#include "core/css/CSSCustomPropertyDeclaration.h" -#include "core/css/CSSIdentifierValue.h" -#include "core/css/StyleSheetContents.h" -#include "core/css/parser/CSSParser.h" -#include "core/css/parser/CSSParserContext.h" - -namespace blink { - -namespace { - -inline bool ContainsId(const CSSProperty** set, - unsigned length, - CSSPropertyID id) { - for (unsigned i = 0; i < length; ++i) { - if (set[i]->IDEquals(id)) - return true; - } - return false; -} - -} // namespace - -MutableCSSPropertyValueSet::MutableCSSPropertyValueSet( - CSSParserMode css_parser_mode) - : CSSPropertyValueSet(css_parser_mode) {} - -MutableCSSPropertyValueSet::MutableCSSPropertyValueSet( - const CSSPropertyValue* properties, - unsigned length) - : CSSPropertyValueSet(kHTMLStandardMode) { - property_vector_.ReserveInitialCapacity(length); - for (unsigned i = 0; i < length; ++i) - property_vector_.UncheckedAppend(properties[i]); -} - -MutableCSSPropertyValueSet::MutableCSSPropertyValueSet( - const CSSPropertyValueSet& other) - : CSSPropertyValueSet(other.CssParserMode()) { - if (other.IsMutable()) { - property_vector_ = ToMutableCSSPropertyValueSet(other).property_vector_; - } else { - property_vector_.ReserveInitialCapacity(other.PropertyCount()); - for (unsigned i = 0; i < other.PropertyCount(); ++i) { - property_vector_.UncheckedAppend( - other.PropertyAt(i).ToCSSPropertyValue()); - } - } -} - -bool MutableCSSPropertyValueSet::RemoveShorthandProperty( - CSSPropertyID property_id) { - StylePropertyShorthand shorthand = shorthandForProperty(property_id); - if (!shorthand.length()) - return false; - - return RemovePropertiesInSet(shorthand.properties(), shorthand.length()); -} - -bool MutableCSSPropertyValueSet::RemovePropertyAtIndex(int property_index, - String* return_text) { - if (property_index == -1) { - if (return_text) - *return_text = ""; - return false; - } - - if (return_text) - *return_text = PropertyAt(property_index).Value().CssText(); - - // A more efficient removal strategy would involve marking entries as empty - // and sweeping them when the vector grows too big. - property_vector_.EraseAt(property_index); - - return true; -} - -template <typename T> -bool MutableCSSPropertyValueSet::RemoveProperty(T property, - String* return_text) { - if (RemoveShorthandProperty(property)) { - // FIXME: Return an equivalent shorthand when possible. - if (return_text) - *return_text = ""; - return true; - } - - int found_property_index = FindPropertyIndex(property); - return RemovePropertyAtIndex(found_property_index, return_text); -} -template CORE_EXPORT bool MutableCSSPropertyValueSet::RemoveProperty( - CSSPropertyID, - String*); -template CORE_EXPORT bool MutableCSSPropertyValueSet::RemoveProperty( - AtomicString, - String*); - -MutableCSSPropertyValueSet::SetResult MutableCSSPropertyValueSet::SetProperty( - CSSPropertyID unresolved_property, - const String& value, - bool important, - SecureContextMode secure_context_mode, - StyleSheetContents* context_style_sheet) { - DCHECK_GE(unresolved_property, firstCSSProperty); - - // Setting the value to an empty string just removes the property in both IE - // and Gecko. Setting it to null seems to produce less consistent results, but - // we treat it just the same. - if (value.IsEmpty()) { - bool did_parse = true; - bool did_change = RemoveProperty(resolveCSSPropertyID(unresolved_property)); - return SetResult{did_parse, did_change}; - } - - // When replacing an existing property value, this moves the property to the - // end of the list. Firefox preserves the position, and MSIE moves the - // property to the beginning. - return CSSParser::ParseValue(this, unresolved_property, value, important, - secure_context_mode, context_style_sheet); -} - -MutableCSSPropertyValueSet::SetResult MutableCSSPropertyValueSet::SetProperty( - const AtomicString& custom_property_name, - const PropertyRegistry* registry, - const String& value, - bool important, - SecureContextMode secure_context_mode, - StyleSheetContents* context_style_sheet, - bool is_animation_tainted) { - if (value.IsEmpty()) { - bool did_parse = true; - bool did_change = RemoveProperty(custom_property_name); - return MutableCSSPropertyValueSet::SetResult{did_parse, did_change}; - } - return CSSParser::ParseValueForCustomProperty( - this, custom_property_name, registry, value, important, - secure_context_mode, context_style_sheet, is_animation_tainted); -} - -void MutableCSSPropertyValueSet::SetProperty(CSSPropertyID property_id, - const CSSValue& value, - bool important) { - StylePropertyShorthand shorthand = shorthandForProperty(property_id); - if (!shorthand.length()) { - SetProperty( - CSSPropertyValue(CSSProperty::Get(property_id), value, important)); - return; - } - - RemovePropertiesInSet(shorthand.properties(), shorthand.length()); - - for (unsigned i = 0; i < shorthand.length(); ++i) { - property_vector_.push_back( - CSSPropertyValue(*shorthand.properties()[i], value, important)); - } -} - -bool MutableCSSPropertyValueSet::SetProperty(const CSSPropertyValue& property, - CSSPropertyValue* slot) { - const AtomicString& name = - (property.Id() == CSSPropertyVariable) - ? ToCSSCustomPropertyDeclaration(property.Value())->GetName() - : g_null_atom; - CSSPropertyValue* to_replace = - slot ? slot : FindCSSPropertyWithID(property.Id(), name); - if (to_replace && *to_replace == property) - return false; - if (to_replace) { - *to_replace = property; - return true; - } - property_vector_.push_back(property); - return true; -} - -bool MutableCSSPropertyValueSet::SetProperty(CSSPropertyID property_id, - CSSValueID identifier, - bool important) { - SetProperty(CSSPropertyValue(CSSProperty::Get(property_id), - *CSSIdentifierValue::Create(identifier), - important)); - return true; -} - -void MutableCSSPropertyValueSet::ParseDeclarationList( - const String& style_declaration, - SecureContextMode secure_context_mode, - StyleSheetContents* context_style_sheet) { - property_vector_.clear(); - - CSSParserContext* context; - if (context_style_sheet) { - context = CSSParserContext::CreateWithStyleSheetContents( - context_style_sheet->ParserContext(), context_style_sheet); - context->SetMode(CssParserMode()); - } else { - context = CSSParserContext::Create(CssParserMode(), secure_context_mode); - } - - CSSParser::ParseDeclarationList(context, this, style_declaration); -} - -bool MutableCSSPropertyValueSet::AddParsedProperties( - const HeapVector<CSSPropertyValue, 256>& properties) { - bool changed = false; - property_vector_.ReserveCapacity(property_vector_.size() + properties.size()); - for (unsigned i = 0; i < properties.size(); ++i) - changed |= SetProperty(properties[i]); - return changed; -} - -bool MutableCSSPropertyValueSet::AddRespectingCascade( - const CSSPropertyValue& property) { - // Only add properties that have no !important counterpart present - if (!PropertyIsImportant(property.Id()) || property.IsImportant()) - return SetProperty(property); - return false; -} - -void MutableCSSPropertyValueSet::MergeAndOverrideOnConflict( - const CSSPropertyValueSet* other) { - unsigned size = other->PropertyCount(); - for (unsigned n = 0; n < size; ++n) { - PropertyReference to_merge = other->PropertyAt(n); - // TODO(leviw): This probably doesn't work correctly with Custom Properties - CSSPropertyValue* old = FindCSSPropertyWithID(to_merge.Id()); - if (old) - SetProperty(to_merge.ToCSSPropertyValue(), old); - else - property_vector_.push_back(to_merge.ToCSSPropertyValue()); - } -} - -void MutableCSSPropertyValueSet::Clear() { - property_vector_.clear(); -} - -bool MutableCSSPropertyValueSet::RemovePropertiesInSet(const CSSProperty** set, - unsigned length) { - if (property_vector_.IsEmpty()) - return false; - - CSSPropertyValue* properties = property_vector_.data(); - unsigned old_size = property_vector_.size(); - unsigned new_index = 0; - for (unsigned old_index = 0; old_index < old_size; ++old_index) { - const CSSPropertyValue& property = properties[old_index]; - if (ContainsId(set, length, property.Id())) - continue; - // Modify property_vector_ in-place since this method is - // performance-sensitive. - properties[new_index++] = properties[old_index]; - } - if (new_index != old_size) { - property_vector_.Shrink(new_index); - return true; - } - return false; -} - -CSSPropertyValue* MutableCSSPropertyValueSet::FindCSSPropertyWithID( - CSSPropertyID property_id, - const AtomicString& custom_property_name) { - int found_property_index = -1; - if (property_id == CSSPropertyVariable && !custom_property_name.IsNull()) { - // TODO(shanestephens): fix call sites so we always have a - // customPropertyName here. - found_property_index = FindPropertyIndex(custom_property_name); - } else { - DCHECK(custom_property_name.IsNull()); - found_property_index = FindPropertyIndex(property_id); - } - if (found_property_index == -1) - return nullptr; - return &property_vector_.at(found_property_index); -} - -bool CSSPropertyValueSet::PropertyMatches( - CSSPropertyID property_id, - const CSSValue& property_value) const { - int found_property_index = FindPropertyIndex(property_id); - if (found_property_index == -1) - return false; - return PropertyAt(found_property_index).Value() == property_value; -} - -void MutableCSSPropertyValueSet::RemoveEquivalentProperties( - const CSSPropertyValueSet* style) { - Vector<CSSPropertyID> properties_to_remove; - unsigned size = property_vector_.size(); - for (unsigned i = 0; i < size; ++i) { - PropertyReference property = PropertyAt(i); - if (style->PropertyMatches(property.Id(), property.Value())) - properties_to_remove.push_back(property.Id()); - } - // FIXME: This should use mass removal. - for (unsigned i = 0; i < properties_to_remove.size(); ++i) - RemoveProperty(properties_to_remove[i]); -} - -void MutableCSSPropertyValueSet::RemoveEquivalentProperties( - const CSSStyleDeclaration* style) { - Vector<CSSPropertyID> properties_to_remove; - unsigned size = property_vector_.size(); - for (unsigned i = 0; i < size; ++i) { - PropertyReference property = PropertyAt(i); - if (style->CssPropertyMatches(property.Id(), &property.Value())) - properties_to_remove.push_back(property.Id()); - } - // FIXME: This should use mass removal. - for (unsigned i = 0; i < properties_to_remove.size(); ++i) - RemoveProperty(properties_to_remove[i]); -} - -CSSStyleDeclaration* MutableCSSPropertyValueSet::EnsureCSSStyleDeclaration() { - // FIXME: get rid of this weirdness of a CSSStyleDeclaration inside of a - // style property set. - if (cssom_wrapper_) { - DCHECK( - !static_cast<CSSStyleDeclaration*>(cssom_wrapper_.Get())->parentRule()); - DCHECK(!cssom_wrapper_->ParentElement()); - return cssom_wrapper_.Get(); - } - cssom_wrapper_ = new PropertySetCSSStyleDeclaration(*this); - return cssom_wrapper_.Get(); -} - -template <typename T> -int MutableCSSPropertyValueSet::FindPropertyIndex(T property) const { - const CSSPropertyValue* begin = property_vector_.data(); - const CSSPropertyValue* end = begin + property_vector_.size(); - - uint16_t id = CSSPropertyValueSet::GetConvertedCSSPropertyID(property); - - const CSSPropertyValue* it = std::find_if( - begin, end, [property, id](const CSSPropertyValue& css_property) -> bool { - return IsPropertyMatch(css_property.Metadata(), *css_property.Value(), - id, property); - }); - - return (it == end) ? -1 : it - begin; -} -template CORE_EXPORT int MutableCSSPropertyValueSet::FindPropertyIndex( - CSSPropertyID) const; -template CORE_EXPORT int MutableCSSPropertyValueSet::FindPropertyIndex( - AtomicString) const; -template CORE_EXPORT int MutableCSSPropertyValueSet::FindPropertyIndex( - AtRuleDescriptorID) const; - -void MutableCSSPropertyValueSet::TraceAfterDispatch(blink::Visitor* visitor) { - visitor->Trace(cssom_wrapper_); - visitor->Trace(property_vector_); - CSSPropertyValueSet::TraceAfterDispatch(visitor); -} - -MutableCSSPropertyValueSet* MutableCSSPropertyValueSet::Create( - CSSParserMode css_parser_mode) { - return new MutableCSSPropertyValueSet(css_parser_mode); -} - -MutableCSSPropertyValueSet* MutableCSSPropertyValueSet::Create( - const CSSPropertyValue* properties, - unsigned count) { - return new MutableCSSPropertyValueSet(properties, count); -} - -} // namespace blink
diff --git a/third_party/WebKit/Source/core/css/MutableCSSPropertyValueSet.h b/third_party/WebKit/Source/core/css/MutableCSSPropertyValueSet.h deleted file mode 100644 index 1d08d83b..0000000 --- a/third_party/WebKit/Source/core/css/MutableCSSPropertyValueSet.h +++ /dev/null
@@ -1,100 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MutableCSSPropertyValueSet_h -#define MutableCSSPropertyValueSet_h - -#include "core/css/CSSPropertyValueSet.h" - -namespace blink { - -class CORE_EXPORT MutableCSSPropertyValueSet : public CSSPropertyValueSet { - public: - ~MutableCSSPropertyValueSet() = default; - static MutableCSSPropertyValueSet* Create(CSSParserMode); - static MutableCSSPropertyValueSet* Create(const CSSPropertyValue* properties, - unsigned count); - - unsigned PropertyCount() const { return property_vector_.size(); } - - // Returns whether this style set was changed. - bool AddParsedProperties(const HeapVector<CSSPropertyValue, 256>&); - bool AddRespectingCascade(const CSSPropertyValue&); - - struct SetResult { - bool did_parse; - bool did_change; - }; - // These expand shorthand properties into multiple properties. - SetResult SetProperty(CSSPropertyID unresolved_property, - const String& value, - bool important, - SecureContextMode, - StyleSheetContents* context_style_sheet = nullptr); - SetResult SetProperty(const AtomicString& custom_property_name, - const PropertyRegistry*, - const String& value, - bool important, - SecureContextMode, - StyleSheetContents* context_style_sheet, - bool is_animation_tainted); - 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); - bool SetProperty(const CSSPropertyValue&, CSSPropertyValue* slot = nullptr); - - template <typename T> // CSSPropertyID or AtomicString - bool RemoveProperty(T property, String* return_text = nullptr); - bool RemovePropertiesInSet(const CSSProperty** set, unsigned length); - void RemoveEquivalentProperties(const CSSPropertyValueSet*); - void RemoveEquivalentProperties(const CSSStyleDeclaration*); - - void MergeAndOverrideOnConflict(const CSSPropertyValueSet*); - - void Clear(); - void ParseDeclarationList(const String& style_declaration, - SecureContextMode, - StyleSheetContents* context_style_sheet); - - CSSStyleDeclaration* EnsureCSSStyleDeclaration(); - - template <typename T> // CSSPropertyID, AtRuleDescriptorID or AtomicString - int FindPropertyIndex(T property) const; - - void TraceAfterDispatch(blink::Visitor*); - - private: - explicit MutableCSSPropertyValueSet(CSSParserMode); - explicit MutableCSSPropertyValueSet(const CSSPropertyValueSet&); - MutableCSSPropertyValueSet(const CSSPropertyValue* properties, - unsigned count); - - bool RemovePropertyAtIndex(int, String* return_text); - - bool RemoveShorthandProperty(CSSPropertyID); - bool RemoveShorthandProperty(const AtomicString& custom_property_name) { - return false; - } - CSSPropertyValue* FindCSSPropertyWithID( - CSSPropertyID, - const AtomicString& custom_property_name = g_null_atom); - Member<PropertySetCSSStyleDeclaration> cssom_wrapper_; - - friend class CSSPropertyValueSet; - - HeapVector<CSSPropertyValue, 4> property_vector_; -}; - -DEFINE_TYPE_CASTS(MutableCSSPropertyValueSet, - CSSPropertyValueSet, - set, - set->IsMutable(), - set.IsMutable()); - -} // namespace blink - -#endif // MutableCSSPropertyValueSet_h
diff --git a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp index 7e6fc67..e6b6d7e 100644 --- a/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp +++ b/third_party/WebKit/Source/core/css/PropertySetCSSStyleDeclaration.cpp
@@ -29,7 +29,6 @@ #include "core/css/CSSKeyframesRule.h" #include "core/css/CSSPropertyValueSet.h" #include "core/css/CSSStyleSheet.h" -#include "core/css/MutableCSSPropertyValueSet.h" #include "core/css/StyleChangeReason.h" #include "core/css/StyleEngine.h" #include "core/dom/Element.h" @@ -166,7 +165,7 @@ CSSPropertyValueSet::PropertyReference property = PropertySet().PropertyAt(i); if (property.Id() == CSSPropertyVariable) return ToCSSCustomPropertyDeclaration(property.Value()).GetName(); - return getPropertyName(property.Id()); + return property.Property().GetPropertyName(); } String AbstractPropertySetCSSStyleDeclaration::cssText() const { @@ -227,7 +226,7 @@ CSSPropertyID shorthand_id = PropertySet().GetPropertyShorthand(property_id); if (!shorthand_id) return String(); - return getPropertyNameString(shorthand_id); + return CSSProperty::Get(shorthand_id).GetPropertyNameString(); } bool AbstractPropertySetCSSStyleDeclaration::IsPropertyImplicit(
diff --git a/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp b/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp index 8960d93..49df7eb 100644 --- a/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp +++ b/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp
@@ -99,7 +99,7 @@ CSSPropertyValueSet::PropertyReference property = property_set_->PropertyAt(all_index_); return StylePropertySerializer::PropertyValueForSerializer( - property_id, &property.Value(), property.IsImportant()); + CSSProperty::Get(property_id), &property.Value(), property.IsImportant()); } bool StylePropertySerializer::CSSPropertyValueSetForSerializer:: @@ -173,7 +173,7 @@ String StylePropertySerializer::GetCustomPropertyText( const PropertyValueForSerializer& property, bool is_not_first_decl) const { - DCHECK_EQ(property.Id(), CSSPropertyVariable); + DCHECK_EQ(property.Property().PropertyID(), CSSPropertyVariable); StringBuilder result; if (is_not_first_decl) result.Append(' '); @@ -190,14 +190,14 @@ return result.ToString(); } -String StylePropertySerializer::GetPropertyText(CSSPropertyID property_id, +String StylePropertySerializer::GetPropertyText(const CSSProperty& property, const String& value, bool is_important, bool is_not_first_decl) const { StringBuilder result; if (is_not_first_decl) result.Append(' '); - result.Append(getPropertyName(property_id)); + result.Append(property.GetPropertyName()); result.Append(": "); result.Append(value); if (is_important) @@ -220,10 +220,9 @@ StylePropertySerializer::PropertyValueForSerializer property = property_set_.PropertyAt(n); - CSSPropertyID property_id = property.Id(); -#if DCHECK_IS_ON() - const CSSProperty& property_class = - CSSProperty::Get(resolveCSSPropertyID(property_id)); + const CSSProperty& property_class = property.Property(); + CSSPropertyID property_id = property_class.PropertyID(); + // Only enabled properties should be part of the style. DCHECK(property_class.IsEnabled()); // All shorthand properties should have been expanded at parse time. @@ -231,14 +230,14 @@ (property_class.IsProperty() && !property_class.IsShorthand())); DCHECK(!property_set_.IsDescriptorContext() || property_class.IsDescriptor()); -#endif switch (property_id) { case CSSPropertyVariable: result.Append(GetCustomPropertyText(property, num_decls++)); continue; case CSSPropertyAll: - result.Append(GetPropertyText(property_id, property.Value()->CssText(), + result.Append(GetPropertyText(property_class, + property.Value()->CssText(), property.IsImportant(), num_decls++)); continue; default: @@ -284,8 +283,9 @@ if (shorthand_result.IsEmpty()) continue; - result.Append(GetPropertyText(shorthand_property, shorthand_result, - property.IsImportant(), num_decls++)); + result.Append(GetPropertyText(CSSProperty::Get(shorthand_property), + shorthand_result, property.IsImportant(), + num_decls++)); serialized_as_shorthand = true; for (unsigned i = 0; i < shorthand.length(); i++) { longhand_serialized.set(shorthand.properties()[i]->PropertyID() - @@ -297,7 +297,7 @@ if (serialized_as_shorthand) continue; - result.Append(GetPropertyText(property_id, property.Value()->CssText(), + result.Append(GetPropertyText(property_class, property.Value()->CssText(), property.IsImportant(), num_decls++)); }
diff --git a/third_party/WebKit/Source/core/css/StylePropertySerializer.h b/third_party/WebKit/Source/core/css/StylePropertySerializer.h index 929366b3..6c55828d 100644 --- a/third_party/WebKit/Source/core/css/StylePropertySerializer.h +++ b/third_party/WebKit/Source/core/css/StylePropertySerializer.h
@@ -58,7 +58,7 @@ StringBuilder& result) const; String OffsetValue() const; String BackgroundRepeatPropertyValue() const; - String GetPropertyText(CSSPropertyID, + String GetPropertyText(const CSSProperty&, const String& value, bool is_important, bool is_not_first_decl) const; @@ -84,20 +84,20 @@ explicit PropertyValueForSerializer( CSSPropertyValueSet::PropertyReference property) : value_(property.Value()), - id_(property.Id()), + property_(property.Property()), is_important_(property.IsImportant()), is_inherited_(property.IsInherited()) {} // TODO(sashab): Make this take a const CSSValue&. - PropertyValueForSerializer(CSSPropertyID id, + PropertyValueForSerializer(const CSSProperty& property, const CSSValue* value, bool is_important) : value_(value), - id_(id), + property_(property), is_important_(is_important), is_inherited_(value->IsInheritedValue()) {} - CSSPropertyID Id() const { return id_; } + const CSSProperty& Property() const { return property_; } const CSSValue* Value() const { return value_; } bool IsImportant() const { return is_important_; } bool IsInherited() const { return is_inherited_; } @@ -105,7 +105,7 @@ private: Member<const CSSValue> value_; - CSSPropertyID id_; + const CSSProperty& property_; bool is_important_; bool is_inherited_; };
diff --git a/third_party/WebKit/Source/core/css/StyleRule.cpp b/third_party/WebKit/Source/core/css/StyleRule.cpp index 44f9876..7feec2a1 100644 --- a/third_party/WebKit/Source/core/css/StyleRule.cpp +++ b/third_party/WebKit/Source/core/css/StyleRule.cpp
@@ -30,11 +30,9 @@ #include "core/css/CSSStyleRule.h" #include "core/css/CSSSupportsRule.h" #include "core/css/CSSViewportRule.h" -#include "core/css/MutableCSSPropertyValueSet.h" #include "core/css/StyleRuleImport.h" #include "core/css/StyleRuleKeyframe.h" #include "core/css/StyleRuleNamespace.h" -#include "core/css/parser/CSSLazyPropertyParser.h" namespace blink {
diff --git a/third_party/WebKit/Source/core/css/StyleRule.h b/third_party/WebKit/Source/core/css/StyleRule.h index 7018056..2218bd9 100644 --- a/third_party/WebKit/Source/core/css/StyleRule.h +++ b/third_party/WebKit/Source/core/css/StyleRule.h
@@ -31,7 +31,6 @@ namespace blink { -class CSSLazyPropertyParser; class CSSRule; class CSSStyleSheet;
diff --git a/third_party/WebKit/Source/core/css/cssom/ComputedStylePropertyMap.cpp b/third_party/WebKit/Source/core/css/cssom/ComputedStylePropertyMap.cpp index 6f5a0f1..d67b2533 100644 --- a/third_party/WebKit/Source/core/css/cssom/ComputedStylePropertyMap.cpp +++ b/third_party/WebKit/Source/core/css/cssom/ComputedStylePropertyMap.cpp
@@ -78,7 +78,7 @@ const CSSValue* value = ComputedStyleCSSValueMapping::Get( *property, *style, nullptr /* layout_object */, StyledNode()); if (value) - callback(getPropertyName(property->PropertyID()), *value); + callback(property->GetPropertyName(), *value); } }
diff --git a/third_party/WebKit/Source/core/css/cssom/FilteredComputedStylePropertyMap.cpp b/third_party/WebKit/Source/core/css/cssom/FilteredComputedStylePropertyMap.cpp index 46b03ce..e553928 100644 --- a/third_party/WebKit/Source/core/css/cssom/FilteredComputedStylePropertyMap.cpp +++ b/third_party/WebKit/Source/core/css/cssom/FilteredComputedStylePropertyMap.cpp
@@ -46,8 +46,10 @@ // are a few tests that rely on this. for (const auto property_id : native_properties_) { const CSSValue* value = GetProperty(property_id); - if (value) - callback(getPropertyNameAtomicString(property_id), *value); + if (value) { + callback(CSSProperty::Get(property_id).GetPropertyNameAtomicString(), + *value); + } } for (const auto& name : custom_properties_) {
diff --git a/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.cpp b/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.cpp index 6f029b5ac..86536ef 100644 --- a/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.cpp +++ b/third_party/WebKit/Source/core/css/cssom/InlineStylePropertyMap.cpp
@@ -6,7 +6,6 @@ #include "core/css/CSSCustomPropertyDeclaration.h" #include "core/css/CSSPropertyValueSet.h" -#include "core/css/MutableCSSPropertyValueSet.h" namespace blink { @@ -41,7 +40,7 @@ ToCSSCustomPropertyDeclaration(property_reference.Value()); callback(decl.GetName(), property_reference.Value()); } else { - callback(getPropertyNameAtomicString(property_reference.Id()), + callback(property_reference.Property().GetPropertyNameAtomicString(), property_reference.Value()); } }
diff --git a/third_party/WebKit/Source/core/css/parser/CSSLazyPropertyParser.h b/third_party/WebKit/Source/core/css/parser/CSSLazyPropertyParser.h deleted file mode 100644 index 00eb0a4b..0000000 --- a/third_party/WebKit/Source/core/css/parser/CSSLazyPropertyParser.h +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CSSLazyPropertyParser_h -#define CSSLazyPropertyParser_h - -#include "platform/heap/GarbageCollected.h" -#include "platform/heap/Heap.h" - -namespace blink { - -class CSSPropertyValueSet; - -// Used for lazily parsing properties. -class CSSLazyPropertyParser - : public GarbageCollectedFinalized<CSSLazyPropertyParser> { - public: - CSSLazyPropertyParser() = default; - virtual ~CSSLazyPropertyParser() = default; - virtual CSSPropertyValueSet* ParseProperties() = 0; - virtual void Trace(blink::Visitor*) {} - DISALLOW_COPY_AND_ASSIGN(CSSLazyPropertyParser); -}; - -} // namespace blink - -#endif // CSSLazyPropertyParser_h
diff --git a/third_party/WebKit/Source/core/css/parser/CSSLazyPropertyParserImpl.h b/third_party/WebKit/Source/core/css/parser/CSSLazyPropertyParserImpl.h index 304e3a6a..27588ae 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSLazyPropertyParserImpl.h +++ b/third_party/WebKit/Source/core/css/parser/CSSLazyPropertyParserImpl.h
@@ -5,7 +5,7 @@ #ifndef CSSLazyPropertyParserImpl_h #define CSSLazyPropertyParserImpl_h -#include "core/css/parser/CSSLazyPropertyParser.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/css/parser/CSSParserTokenRange.h" #include "core/css/parser/CSSTokenizer.h"
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParser.h b/third_party/WebKit/Source/core/css/parser/CSSParser.h index f60725f1..4b9945a6 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParser.h +++ b/third_party/WebKit/Source/core/css/parser/CSSParser.h
@@ -8,7 +8,7 @@ #include <memory> #include "core/CSSPropertyNames.h" #include "core/CoreExport.h" -#include "core/css/MutableCSSPropertyValueSet.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/css/parser/CSSParserContext.h" namespace blink {
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp index 7308c13..03d8ee93 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp +++ b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.cpp
@@ -10,8 +10,6 @@ #include "core/css/CSSCustomPropertyDeclaration.h" #include "core/css/CSSKeyframesRule.h" #include "core/css/CSSStyleSheet.h" -#include "core/css/ImmutableCSSPropertyValueSet.h" -#include "core/css/MutableCSSPropertyValueSet.h" #include "core/css/PropertyRegistry.h" #include "core/css/StyleRuleImport.h" #include "core/css/StyleRuleKeyframe.h"
diff --git a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h index 9a6e3cde..2dea9c7 100644 --- a/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h +++ b/third_party/WebKit/Source/core/css/parser/CSSParserImpl.h
@@ -11,7 +11,7 @@ #include "core/CSSPropertyNames.h" #include "core/css/CSSPropertySourceData.h" #include "core/css/CSSPropertyValue.h" -#include "core/css/MutableCSSPropertyValueSet.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/css/parser/CSSParserTokenRange.h" #include "platform/heap/Handle.h" #include "platform/wtf/Vector.h"
diff --git a/third_party/WebKit/Source/core/css/properties/CSSParsingUtils.cpp b/third_party/WebKit/Source/core/css/properties/CSSParsingUtils.cpp index a95066b..a7a9db5 100644 --- a/third_party/WebKit/Source/core/css/properties/CSSParsingUtils.cpp +++ b/third_party/WebKit/Source/core/css/properties/CSSParsingUtils.cpp
@@ -1358,8 +1358,6 @@ return CombineToRangeListOrNull(start_weight, end_weight); } -// TODO(bugsnash): move this to the FontFeatureSettings class when it is no -// longer being used by methods outside of the property class CSSValue* ConsumeFontFeatureSettings(CSSParserTokenRange& range) { if (range.Peek().Id() == CSSValueNormal) return CSSPropertyParserHelpers::ConsumeIdent(range);
diff --git a/third_party/WebKit/Source/core/css/properties/CSSPropertyBaseCustom.cpp b/third_party/WebKit/Source/core/css/properties/CSSPropertyBaseCustom.cpp index 9fbd964..c991e34 100644 --- a/third_party/WebKit/Source/core/css/properties/CSSPropertyBaseCustom.cpp +++ b/third_party/WebKit/Source/core/css/properties/CSSPropertyBaseCustom.cpp
@@ -74,6 +74,29 @@ return *shorthand_properties[kBottomSide]; } +WTF::String CSSProperty::GetJSPropertyName() const { + char result[maxCSSPropertyNameLength + 1]; + const char* cssPropertyName = GetPropertyName(); + const char* propertyNamePointer = cssPropertyName; + if (!propertyNamePointer) + return g_empty_string; + + char* resultPointer = result; + while (char character = *propertyNamePointer++) { + if (character == '-') { + char nextCharacter = *propertyNamePointer++; + if (!nextCharacter) + break; + character = (propertyNamePointer - 2 != cssPropertyName) + ? ToASCIIUpper(nextCharacter) + : nextCharacter; + } + *resultPointer++ = character; + } + *resultPointer = '\0'; + return String(result); +} + void CSSProperty::FilterEnabledCSSPropertiesIntoVector( const CSSPropertyID* properties, size_t propertyCount,
diff --git a/third_party/WebKit/Source/core/css/resolver/MatchResultTest.cpp b/third_party/WebKit/Source/core/css/resolver/MatchResultTest.cpp index 11f36f7..b526f14 100644 --- a/third_party/WebKit/Source/core/css/resolver/MatchResultTest.cpp +++ b/third_party/WebKit/Source/core/css/resolver/MatchResultTest.cpp
@@ -4,7 +4,7 @@ #include "core/css/resolver/MatchResult.h" -#include "core/css/MutableCSSPropertyValueSet.h" +#include "core/css/CSSPropertyValueSet.h" #include "testing/gtest/include/gtest/gtest.h" namespace blink {
diff --git a/third_party/WebKit/Source/core/css/resolver/ViewportStyleResolver.cpp b/third_party/WebKit/Source/core/css/resolver/ViewportStyleResolver.cpp index 87498d4..3554660 100644 --- a/third_party/WebKit/Source/core/css/resolver/ViewportStyleResolver.cpp +++ b/third_party/WebKit/Source/core/css/resolver/ViewportStyleResolver.cpp
@@ -32,11 +32,11 @@ #include "core/CSSValueKeywords.h" #include "core/css/CSSDefaultStyleSheets.h" #include "core/css/CSSPrimitiveValueMappings.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/css/CSSStyleSheet.h" #include "core/css/CSSToLengthConversionData.h" #include "core/css/DocumentStyleSheetCollection.h" #include "core/css/MediaValuesInitialViewport.h" -#include "core/css/MutableCSSPropertyValueSet.h" #include "core/css/StyleRule.h" #include "core/css/StyleRuleImport.h" #include "core/css/StyleSheetContents.h"
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp index c88b5b8..6c44c88 100644 --- a/third_party/WebKit/Source/core/dom/Document.cpp +++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -3269,6 +3269,12 @@ (!GetLayoutViewItem().FirstChild() || GetLayoutViewItem().NeedsLayout())) View()->UpdateLayout(); + + // TODO(bokan): This is a temporary fix to https://crbug.com/788486. + // There's some better cleanups that should be done to follow-up: + // https://crbug.com/795381. + if (View() && goto_anchor_needed_after_stylesheets_load_) + View()->ProcessUrlFragment(url_); } load_event_progress_ = kLoadEventCompleted;
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp index 485e8f5..a357a5a 100644 --- a/third_party/WebKit/Source/core/dom/Element.cpp +++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -37,10 +37,10 @@ #include "core/animation/css/CSSAnimations.h" #include "core/css/CSSIdentifierValue.h" #include "core/css/CSSPrimitiveValue.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/css/CSSSelectorWatch.h" #include "core/css/CSSStyleSheet.h" #include "core/css/CSSValue.h" -#include "core/css/ImmutableCSSPropertyValueSet.h" #include "core/css/PropertySetCSSStyleDeclaration.h" #include "core/css/SelectorQuery.h" #include "core/css/StyleChangeReason.h"
diff --git a/third_party/WebKit/Source/core/dom/ElementData.cpp b/third_party/WebKit/Source/core/dom/ElementData.cpp index ee5e5c6..7e93da8d 100644 --- a/third_party/WebKit/Source/core/dom/ElementData.cpp +++ b/third_party/WebKit/Source/core/dom/ElementData.cpp
@@ -31,8 +31,6 @@ #include "core/dom/ElementData.h" #include "core/css/CSSPropertyValueSet.h" -#include "core/css/ImmutableCSSPropertyValueSet.h" -#include "core/css/MutableCSSPropertyValueSet.h" #include "core/dom/QualifiedName.h" #include "platform/wtf/Vector.h"
diff --git a/third_party/WebKit/Source/core/dom/PresentationAttributeStyle.cpp b/third_party/WebKit/Source/core/dom/PresentationAttributeStyle.cpp index 690571b..612c96b 100644 --- a/third_party/WebKit/Source/core/dom/PresentationAttributeStyle.cpp +++ b/third_party/WebKit/Source/core/dom/PresentationAttributeStyle.cpp
@@ -33,7 +33,7 @@ #include <algorithm> #include "base/macros.h" -#include "core/css/MutableCSSPropertyValueSet.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/dom/Attribute.h" #include "core/dom/Element.h" #include "core/html/forms/HTMLInputElement.h"
diff --git a/third_party/WebKit/Source/core/editing/EditingStyleTest.cpp b/third_party/WebKit/Source/core/editing/EditingStyleTest.cpp index da71294..cfded12 100644 --- a/third_party/WebKit/Source/core/editing/EditingStyleTest.cpp +++ b/third_party/WebKit/Source/core/editing/EditingStyleTest.cpp
@@ -4,7 +4,7 @@ #include "core/editing/EditingStyle.h" -#include "core/css/MutableCSSPropertyValueSet.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/dom/Document.h" #include "core/editing/testing/EditingTestBase.h" #include "core/html/HTMLBodyElement.h"
diff --git a/third_party/WebKit/Source/core/editing/Editor.cpp b/third_party/WebKit/Source/core/editing/Editor.cpp index d63d5f8..cbe6380 100644 --- a/third_party/WebKit/Source/core/editing/Editor.cpp +++ b/third_party/WebKit/Source/core/editing/Editor.cpp
@@ -32,7 +32,7 @@ #include "core/clipboard/DataTransfer.h" #include "core/clipboard/Pasteboard.h" #include "core/css/CSSComputedStyleDeclaration.h" -#include "core/css/MutableCSSPropertyValueSet.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/dom/AXObjectCache.h" #include "core/dom/DocumentFragment.h" #include "core/dom/ElementTraversal.h"
diff --git a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp index 618cc9e..ddfb1c9 100644 --- a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommand.cpp
@@ -30,7 +30,6 @@ #include "core/css/CSSComputedStyleDeclaration.h" #include "core/css/CSSPrimitiveValue.h" #include "core/css/CSSPropertyValueSet.h" -#include "core/css/MutableCSSPropertyValueSet.h" #include "core/dom/Document.h" #include "core/dom/NodeList.h" #include "core/dom/NodeTraversal.h"
diff --git a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommandTest.cpp b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommandTest.cpp index aed45d26..8b02f30 100644 --- a/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommandTest.cpp +++ b/third_party/WebKit/Source/core/editing/commands/ApplyStyleCommandTest.cpp
@@ -4,7 +4,7 @@ #include "core/editing/commands/ApplyStyleCommand.h" -#include "core/css/MutableCSSPropertyValueSet.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/dom/Document.h" #include "core/editing/EditingStyle.h" #include "core/editing/FrameSelection.h"
diff --git a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp index a8d92be0..8292ea8 100644 --- a/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/EditorCommand.cpp
@@ -33,8 +33,8 @@ #include "core/clipboard/Pasteboard.h" #include "core/css/CSSComputedStyleDeclaration.h" #include "core/css/CSSIdentifierValue.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/css/CSSValueList.h" -#include "core/css/MutableCSSPropertyValueSet.h" #include "core/dom/DocumentFragment.h" #include "core/dom/TagCollection.h" #include "core/dom/events/Event.h"
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp b/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp index acd4086..6f279e1c 100644 --- a/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/InsertParagraphSeparatorCommand.cpp
@@ -243,6 +243,8 @@ PositionAvoidingSpecialElementBoundary(insertion_position, editing_state); if (editing_state->IsAborted()) return; + // InsertTextCommandTest.AnchorElementWithBlockCrash reaches here. + ABORT_EDITING_COMMAND_IF(!start_block->parentNode()); if (list_child == enclosing_anchor) { // |positionAvoidingSpecialElementBoundary()| creates new A element and // move to another place.
diff --git a/third_party/WebKit/Source/core/editing/commands/InsertTextCommandTest.cpp b/third_party/WebKit/Source/core/editing/commands/InsertTextCommandTest.cpp index d2e77961..dd2a6b2f 100644 --- a/third_party/WebKit/Source/core/editing/commands/InsertTextCommandTest.cpp +++ b/third_party/WebKit/Source/core/editing/commands/InsertTextCommandTest.cpp
@@ -242,4 +242,41 @@ Selection().GetSelectionInDOMTree())); } +// http://crbug.com/792548 +TEST_F(InsertTextCommandTest, AnchorElementWithBlockCrash) { + GetDocument().setDesignMode("on"); + SetBodyContent("<a href=\"www\" style=\"display:block\">"); + // We need the below DOM with selection. + // <a href=\"www\" style=\"display:block\"> + // <a href=\"www\" style=\"display: inline !important;\"> + // <i>^home|</i> + // </a> + // </a> + // Since the HTML parser rejects it as there are nested <a> elements. + // We are contructing the remaining DOM manually. + Element* const anchor = GetDocument().QuerySelector("a"); + Element* nested_anchor = GetDocument().createElement("a"); + Element* iElement = GetDocument().createElement("i"); + + nested_anchor->setAttribute("href", "www"); + iElement->SetInnerHTMLFromString("home"); + + anchor->AppendChild(nested_anchor); + nested_anchor->AppendChild(iElement); + + Node* const iElement_text_node = iElement->firstChild(); + Selection().SetSelection( + SelectionInDOMTree::Builder() + .SetBaseAndExtent(Position(iElement_text_node, 0), + Position(iElement_text_node, 4)) + .Build()); + // Crash happens here with when '\n' is inserted. + GetDocument().execCommand("inserttext", false, "a\n", ASSERT_NO_EXCEPTION); + EXPECT_EQ( + "<i style=\"display: block;\">" + "<a href=\"www\" style=\"display: block;\">a</a>" + "</i>|", + GetSelectionTextFromBody(Selection().GetSelectionInDOMTree())); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/editing/commands/RemoveFormatCommand.cpp b/third_party/WebKit/Source/core/editing/commands/RemoveFormatCommand.cpp index c2c8ccc..62e7182 100644 --- a/third_party/WebKit/Source/core/editing/commands/RemoveFormatCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/RemoveFormatCommand.cpp
@@ -27,7 +27,7 @@ #include "core/editing/commands/RemoveFormatCommand.h" #include "core/CSSValueKeywords.h" -#include "core/css/MutableCSSPropertyValueSet.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/dom/Document.h" #include "core/dom/Element.h" #include "core/editing/EditingStyle.h"
diff --git a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp index 7ce1be0..4c246ce 100644 --- a/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp +++ b/third_party/WebKit/Source/core/editing/commands/ReplaceSelectionCommand.cpp
@@ -29,8 +29,8 @@ #include "base/macros.h" #include "bindings/core/v8/ExceptionState.h" #include "core/CSSPropertyNames.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/css/CSSStyleDeclaration.h" -#include "core/css/MutableCSSPropertyValueSet.h" #include "core/dom/Document.h" #include "core/dom/DocumentFragment.h" #include "core/dom/Element.h"
diff --git a/third_party/WebKit/Source/core/editing/serializers/StyledMarkupAccumulator.cpp b/third_party/WebKit/Source/core/editing/serializers/StyledMarkupAccumulator.cpp index b3f9e0f..71b5f95 100644 --- a/third_party/WebKit/Source/core/editing/serializers/StyledMarkupAccumulator.cpp +++ b/third_party/WebKit/Source/core/editing/serializers/StyledMarkupAccumulator.cpp
@@ -29,7 +29,7 @@ #include "core/editing/serializers/StyledMarkupAccumulator.h" -#include "core/css/MutableCSSPropertyValueSet.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/dom/Text.h" #include "core/editing/EditingUtilities.h" #include "core/editing/EphemeralRange.h"
diff --git a/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.cpp b/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.cpp index b698f53..bf9ef57 100644 --- a/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.cpp +++ b/third_party/WebKit/Source/core/editing/serializers/StyledMarkupSerializer.cpp
@@ -30,7 +30,7 @@ #include "core/editing/serializers/StyledMarkupSerializer.h" #include "base/macros.h" -#include "core/css/MutableCSSPropertyValueSet.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/dom/Document.h" #include "core/dom/Element.h" #include "core/dom/ElementShadow.h"
diff --git a/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.cpp b/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.cpp index 6a2f83e..91680718 100644 --- a/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.cpp +++ b/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.cpp
@@ -378,8 +378,7 @@ // TODO(dgozman): we should actually pass the view instead of frame, but // during remote->local transition we cannot access mainFrameImpl() yet, so // we have to store the frame which will become the main frame later. - session->Append( - InspectorEmulationAgent::Create(web_local_frame_impl_, this)); + session->Append(new InspectorEmulationAgent(web_local_frame_impl_)); } // Call session init callbacks registered from higher layers @@ -468,16 +467,6 @@ it.value->SetLayerTreeId(layer_tree_id_); } -void WebDevToolsAgentImpl::EnableTracing(const String& category_filter) { - if (client_) - client_->EnableTracing(category_filter); -} - -void WebDevToolsAgentImpl::DisableTracing() { - if (client_) - client_->DisableTracing(); -} - void WebDevToolsAgentImpl::ShowReloadingBlanket() { for (auto& it : overlay_agents_) it.value->ShowReloadingBlanket(); @@ -488,11 +477,6 @@ it.value->HideReloadingBlanket(); } -void WebDevToolsAgentImpl::SetCPUThrottlingRate(double rate) { - if (client_) - client_->SetCPUThrottlingRate(rate); -} - void WebDevToolsAgentImpl::DispatchOnInspectorBackend( int session_id, int call_id,
diff --git a/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.h b/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.h index 7a9d1ad7..691062ac 100644 --- a/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.h +++ b/third_party/WebKit/Source/core/exported/WebDevToolsAgentImpl.h
@@ -34,7 +34,6 @@ #include <memory> #include "core/CoreExport.h" -#include "core/inspector/InspectorEmulationAgent.h" #include "core/inspector/InspectorLayerTreeAgent.h" #include "core/inspector/InspectorPageAgent.h" #include "core/inspector/InspectorSession.h" @@ -62,7 +61,6 @@ class CORE_EXPORT WebDevToolsAgentImpl final : public GarbageCollectedFinalized<WebDevToolsAgentImpl>, public WebDevToolsAgent, - public InspectorEmulationAgent::Client, public InspectorTracingAgent::Client, public InspectorPageAgent::Client, public InspectorSession::Client, @@ -108,14 +106,9 @@ bool include_view_agents); // InspectorTracingAgent::Client implementation. - void EnableTracing(const WTF::String& category_filter) override; - void DisableTracing() override; void ShowReloadingBlanket() override; void HideReloadingBlanket() override; - // InspectorEmulationAgent::Client implementation. - void SetCPUThrottlingRate(double) override; - // InspectorPageAgent::Client implementation. void PageLayoutInvalidated(bool resized) override; void WaitForCreateWindow(InspectorPageAgent*, LocalFrame*) override;
diff --git a/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.cpp b/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.cpp index 4d8fe277..6636f9a2 100644 --- a/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.cpp +++ b/third_party/WebKit/Source/core/exported/WebSharedWorkerImpl.cpp
@@ -340,11 +340,14 @@ GetWorkerThread()->Start( std::move(global_scope_creation_params), thread_startup_data, - std::make_unique<GlobalScopeInspectorCreationParams>( - worker_inspector_proxy_->ShouldPauseOnWorkerStart(document)), - task_runners, source_code); + worker_inspector_proxy_->ShouldPauseOnWorkerStart(document), + task_runners); worker_inspector_proxy_->WorkerThreadCreated(document, GetWorkerThread(), url_); + // TODO(nhiroki): Support module workers (https://crbug.com/680046). + GetWorkerThread()->EvaluateClassicScript(url_, source_code, + nullptr /* cached_meta_data */, + v8_inspector::V8StackTraceId()); client_->WorkerScriptLoaded(); }
diff --git a/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.cpp b/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.cpp index b862052..57146de 100644 --- a/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.cpp +++ b/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.cpp
@@ -26,7 +26,6 @@ #include "platform/wtf/Assertions.h" #include "public/platform/Platform.h" #include "public/platform/WebGestureCurve.h" -#include "public/web/WebActiveWheelFlingParameters.h" #include "public/web/WebLocalFrame.h" #include "public/web/WebWidgetClient.h" @@ -483,26 +482,6 @@ return event_result; } -void WebFrameWidgetBase::TransferActiveWheelFlingAnimation( - const WebActiveWheelFlingParameters& parameters) { - TRACE_EVENT0("blink", - "WebFrameWidgetBase::TransferActiveWheelFlingAnimation"); - DCHECK(!gesture_animation_); - position_on_fling_start_ = parameters.point; - global_position_on_fling_start_ = parameters.global_point; - fling_modifier_ = parameters.modifiers; - std::unique_ptr<WebGestureCurve> curve = - Platform::Current()->CreateFlingAnimationCurve( - parameters.source_device, WebFloatPoint(parameters.delta), - parameters.cumulative_scroll); - DCHECK(curve); - gesture_animation_ = WebActiveGestureAnimation::CreateWithTimeOffset( - std::move(curve), this, parameters.start_time); - DCHECK_NE(parameters.source_device, kWebGestureDeviceUninitialized); - fling_source_device_ = parameters.source_device; - ScheduleAnimation(); -} - WebLocalFrame* WebFrameWidgetBase::FocusedWebLocalFrameInWidget() const { return WebLocalFrameImpl::FromFrame(FocusedLocalFrameInWidget()); }
diff --git a/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.h b/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.h index 7611e25..3073065 100644 --- a/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.h +++ b/third_party/WebKit/Source/core/frame/WebFrameWidgetBase.h
@@ -88,8 +88,6 @@ WebDragOperation) override; void DragSourceSystemDragEnded() override; - void TransferActiveWheelFlingAnimation( - const WebActiveWheelFlingParameters&) override; WebLocalFrame* FocusedWebLocalFrameInWidget() const override; // Called when a drag-n-drop operation should begin.
diff --git a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp index 848c373..6fe1f827 100644 --- a/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp +++ b/third_party/WebKit/Source/core/frame/WebLocalFrameImpl.cpp
@@ -666,7 +666,8 @@ const WebSecurityOrigin& security_origin) { DCHECK(GetFrame()); DOMWrapperWorld::SetIsolatedWorldSecurityOrigin( - world_id, security_origin.Get()->IsolatedCopy()); + world_id, + security_origin.Get() ? security_origin.Get()->IsolatedCopy() : nullptr); } void WebLocalFrameImpl::SetIsolatedWorldContentSecurityPolicy(
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp index accfb7f..de935f05 100644 --- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp
@@ -70,10 +70,10 @@ #include "core/probe/CoreProbes.h" #include "gpu/config/gpu_feature_info.h" #include "platform/Histogram.h" +#include "platform/graphics/Canvas2DLayerBridge.h" #include "platform/graphics/CanvasHeuristicParameters.h" #include "platform/graphics/CanvasMetrics.h" #include "platform/graphics/GraphicsLayer.h" -#include "platform/graphics/ImageBuffer.h" #include "platform/graphics/OffscreenCanvasFrameDispatcherImpl.h" #include "platform/graphics/gpu/AcceleratedImageBufferSurface.h" #include "platform/graphics/gpu/SharedGpuContext.h" @@ -121,7 +121,7 @@ const int kUndefinedQualityValue = -1.0; scoped_refptr<StaticBitmapImage> CreateTransparentImage(const IntSize& size) { - if (!ImageBuffer::CanCreateImageBuffer(size)) + if (!IsValidImageSize(size)) return nullptr; sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(size.Width(), size.Height()); @@ -139,8 +139,8 @@ size_(kDefaultWidth, kDefaultHeight), ignore_reset_(false), origin_clean_(true), - did_fail_to_create_image_buffer_(false), - image_buffer_is_clear_(false), + did_fail_to_create_buffer_(false), + buffer_is_clear_(false), surface_layer_bridge_(nullptr), gpu_memory_usage_(0), externally_allocated_memory_(0), @@ -173,9 +173,9 @@ context_ = nullptr; } - if (image_buffer_) { - image_buffer_->OnCanvasDisposed(); - image_buffer_ = nullptr; + if (canvas2d_buffer_) { + canvas2d_buffer_->SetCanvasResourceHost(nullptr); + canvas2d_buffer_ = nullptr; } if (gpu_memory_usage_) { @@ -339,8 +339,7 @@ } bool HTMLCanvasElement::IsPaintable() const { - return (context_ && context_->IsPaintable()) || - ImageBuffer::CanCreateImageBuffer(Size()); + return (context_ && context_->IsPaintable()) || IsValidImageSize(Size()); } bool HTMLCanvasElement::IsAccelerated() const { @@ -380,7 +379,7 @@ void HTMLCanvasElement::DidDraw(const FloatRect& rect) { if (rect.IsEmpty()) return; - image_buffer_is_clear_ = false; + buffer_is_clear_ = false; ClearCopiedImage(); if (GetLayoutObject() && !LowLatencyEnabled()) GetLayoutObject()->SetMayNeedPaintInvalidation(); @@ -392,8 +391,8 @@ } else { dirty_rect_.Unite(rect); } - if (Is2d() && GetImageBuffer()) - GetImageBuffer()->DidDraw(rect); + if (Is2d() && canvas2d_buffer_) + canvas2d_buffer_->DidDraw(rect); } void HTMLCanvasElement::DidDraw() { @@ -402,7 +401,7 @@ void HTMLCanvasElement::FinalizeFrame() { TRACE_EVENT0("blink", "HTMLCanvasElement::FinalizeFrame"); - if (GetImageBuffer()) { + if (canvas2d_buffer_) { // Compute to determine whether disable accleration is needed if (IsAccelerated() && CanvasHeuristicParameters::kGPUReadbackForcesNoAcceleration && @@ -421,13 +420,14 @@ } if (!LowLatencyEnabled()) - image_buffer_->FinalizeFrame(); + canvas2d_buffer_->FinalizeFrame(); if (LowLatencyEnabled() && !dirty_rect_.IsEmpty()) { // Push a frame double start_time = WTF::CurrentTimeTicksInSeconds(); - scoped_refptr<StaticBitmapImage> image = image_buffer_->NewImageSnapshot( - kPreferAcceleration, kSnapshotReasonLowLatencyFrame); + scoped_refptr<StaticBitmapImage> image = + canvas2d_buffer_->NewImageSnapshot(kPreferAcceleration, + kSnapshotReasonLowLatencyFrame); FloatRect src_rect(0, 0, Size().Width(), Size().Height()); dirty_rect_.Intersect(src_rect); IntRect int_dirty = EnclosingIntRect(dirty_rect_); @@ -453,13 +453,12 @@ } void HTMLCanvasElement::DisableAcceleration() { - // Create and configure an unaccelerated surface. - std::unique_ptr<ImageBufferSurface> surface = - CreateUnacceleratedImageBufferSurface(); + // Create and configure an unaccelerated Canvas2DLayerBridge. + std::unique_ptr<Canvas2DLayerBridge> bridge = CreateUnaccelerated2dBuffer(); - if (surface && image_buffer_) { - RestoreCanvasMatrixClipStack(surface->Canvas()); - image_buffer_->SetSurface(std::move(surface)); + if (bridge && canvas2d_buffer_) { + RestoreCanvasMatrixClipStack(bridge->Canvas()); + ReplaceExistingCanvas2DBuffer(std::move(bridge)); UpdateMemoryUsage(); } @@ -508,8 +507,8 @@ if (dirty_rect_.IsEmpty()) return; - if (GetImageBuffer()) { - image_buffer_->DoPaintInvalidation(invalidation_rect); + if (canvas2d_buffer_) { + canvas2d_buffer_->DoPaintInvalidation(invalidation_rect); } } @@ -558,7 +557,7 @@ dirty_rect_ = FloatRect(); - bool had_image_buffer = GetImageBuffer(); + bool had_image_buffer = HasImageBuffer(); unsigned w = 0; AtomicString value = getAttribute(widthAttr); @@ -583,8 +582,8 @@ // If the size of an existing buffer matches, we can just clear it instead of // reallocating. This optimization is only done for 2D canvases for now. if (had_image_buffer && old_size == new_size && Is2d()) { - if (!image_buffer_is_clear_) { - image_buffer_is_clear_ = true; + if (!buffer_is_clear_) { + buffer_is_clear_ = true; context_->ClearRect(0, 0, width(), height()); } return; @@ -673,11 +672,11 @@ if (Is3d()) { context_->SetFilterQuality(filter_quality); - } else if (GetImageBuffer()) { - image_buffer_->SetFilterQuality(filter_quality); + } else if (canvas2d_buffer_) { + canvas2d_buffer_->SetFilterQuality(filter_quality); } - if (GetImageBuffer() && !image_buffer_is_clear_) + if (HasImageBuffer() && !buffer_is_clear_) PaintTiming::From(GetDocument()).MarkFirstContentfulPaint(); if (!PaintsIntoCanvasBuffer() && !GetDocument().Printing()) @@ -697,14 +696,23 @@ return; context_->PaintRenderingResultsToCanvas(kFrontBuffer); - if (GetImageBuffer()) { + if (HasImageBuffer()) { if (!context.ContextDisabled()) { SkBlendMode composite_operator = !context_ || context_->CreationAttributes().alpha() ? SkBlendMode::kSrcOver : SkBlendMode::kSrc; - GetImageBuffer()->Draw(context, PixelSnappedIntRect(r), nullptr, - composite_operator); + FloatRect src_rect = FloatRect(FloatPoint(), FloatSize(Size())); + scoped_refptr<StaticBitmapImage> snapshot = + NewImageSnapshot(kPreferAcceleration, kSnapshotReasonPaint); + if (snapshot) { + // GraphicsContext cannot handle gpu resource serialization. + snapshot = snapshot->MakeUnaccelerated(); + DCHECK(!snapshot->IsTextureBacked()); + context.DrawImage(snapshot.get(), Image::kSyncDecode, + PixelSnappedIntRect(r), &src_rect, + composite_operator); + } } } else { // When alpha is false, we should draw to opaque black. @@ -725,13 +733,13 @@ } bool HTMLCanvasElement::IsAnimated2d() const { - return Is2d() && GetImageBuffer() && - GetImageBuffer()->WasDrawnToAfterSnapshot(); + return Is2d() && canvas2d_buffer_ && + canvas2d_buffer_->WasDrawnToAfterSnapshot(); } void HTMLCanvasElement::SetSurfaceSize(const IntSize& size) { size_ = size; - did_fail_to_create_image_buffer_ = false; + did_fail_to_create_buffer_ = false; DiscardImageBuffer(); ClearCopiedImage(); if (Is2d() && context_->isContextLost()) { @@ -746,12 +754,6 @@ ToDataURLInternal(ImageEncoderUtils::kDefaultMimeType, 0, kFrontBuffer)); } -void HTMLCanvasElement::PrepareSurfaceForPaintingIfNeeded() { - DCHECK(Is2d()); // This function is called by the 2d context - if (GetOrCreateImageBuffer()) - image_buffer_->PrepareSurfaceForPaintingIfNeeded(); -} - scoped_refptr<StaticBitmapImage> HTMLCanvasElement::ToStaticBitmapImage( SourceDrawingBuffer source_buffer, AccelerationHint hint, @@ -762,8 +764,8 @@ if (Is3d()) { if (context_->CreationAttributes().premultipliedAlpha()) { context_->PaintRenderingResultsToCanvas(source_buffer); - if (GetImageBuffer()) - image_bitmap = GetImageBuffer()->NewImageSnapshot(hint, reason); + if (webgl_buffer_) + image_bitmap = webgl_buffer_->NewImageSnapshot(hint, reason); } else { scoped_refptr<Uint8Array> data_array = context_->PaintRenderingResultsToDataArray(source_buffer); @@ -780,8 +782,8 @@ } } else if (context_ || PlaceholderFrame()) { DCHECK(Is2d() || PlaceholderFrame()); - if (GetImageBuffer()) { - image_bitmap = GetImageBuffer()->NewImageSnapshot(hint, reason); + if (canvas2d_buffer_) { + image_bitmap = canvas2d_buffer_->NewImageSnapshot(hint, reason); } else if (PlaceholderFrame()) { DCHECK(PlaceholderFrame()->OriginClean()); image_bitmap = PlaceholderFrame(); @@ -990,8 +992,8 @@ return true; } -std::unique_ptr<ImageBufferSurface> -HTMLCanvasElement::CreateWebGLImageBufferSurface() { +std::unique_ptr<AcceleratedImageBufferSurface> +HTMLCanvasElement::CreateWebGLBuffer() { DCHECK(Is3d()); // If 3d, but the use of the canvas will be for non-accelerated content // then make a non-accelerated ImageBuffer. This means copying the internal @@ -999,12 +1001,12 @@ auto surface = std::make_unique<AcceleratedImageBufferSurface>(Size(), ColorParams()); if (surface->IsValid()) - return std::move(surface); + return surface; return nullptr; } -std::unique_ptr<ImageBufferSurface> -HTMLCanvasElement::CreateAcceleratedImageBufferSurface(int* msaa_sample_count) { +std::unique_ptr<Canvas2DLayerBridge> +HTMLCanvasElement::CreateAccelerated2dBuffer(int* msaa_sample_count) { if (GetDocument().GetSettings()) { *msaa_sample_count = GetDocument().GetSettings()->GetAccelerated2dCanvasMSAASampleCount(); @@ -1024,17 +1026,17 @@ CanvasMetrics::CountCanvasContextUsage( CanvasMetrics::kGPUAccelerated2DCanvasImageBufferCreated); - return std::move(surface); + return surface; } -std::unique_ptr<ImageBufferSurface> -HTMLCanvasElement::CreateUnacceleratedImageBufferSurface() { +std::unique_ptr<Canvas2DLayerBridge> +HTMLCanvasElement::CreateUnaccelerated2dBuffer() { auto surface = std::make_unique<Canvas2DLayerBridge>( Size(), 0, Canvas2DLayerBridge::kDisableAcceleration, ColorParams()); if (surface->IsValid()) { CanvasMetrics::CountCanvasContextUsage( CanvasMetrics::kUnaccelerated2DCanvasImageBufferCreated); - return std::move(surface); + return surface; } CanvasMetrics::CountCanvasContextUsage( @@ -1042,44 +1044,38 @@ return nullptr; } -void HTMLCanvasElement::CreateImageBuffer() { - CreateImageBufferInternal(nullptr); - if (did_fail_to_create_image_buffer_ && Is2d() && !Size().IsEmpty()) - context_->LoseContext(CanvasRenderingContext::kSyntheticLostContext); -} - void HTMLCanvasElement::CreateImageBufferInternal( - std::unique_ptr<ImageBufferSurface> external_surface) { - DCHECK(!image_buffer_); + std::unique_ptr<Canvas2DLayerBridge> external_canvas2d_bridge) { + DCHECK(!canvas2d_buffer_ && !webgl_buffer_); - did_fail_to_create_image_buffer_ = true; - image_buffer_is_clear_ = true; + did_fail_to_create_buffer_ = true; + buffer_is_clear_ = true; - if (!ImageBuffer::CanCreateImageBuffer(Size())) + if (!IsValidImageSize(Size())) return; int msaa_sample_count = 0; - std::unique_ptr<ImageBufferSurface> surface; - if (external_surface) { - if (external_surface->IsValid()) - surface = std::move(external_surface); + if (external_canvas2d_bridge) { + if (external_canvas2d_bridge->IsValid()) + canvas2d_buffer_ = std::move(external_canvas2d_bridge); } else if (Is3d()) { - surface = CreateWebGLImageBufferSurface(); + webgl_buffer_ = CreateWebGLBuffer(); } else { if (ShouldAccelerate(kNormalAccelerationCriteria)) { - surface = CreateAcceleratedImageBufferSurface(&msaa_sample_count); + canvas2d_buffer_ = CreateAccelerated2dBuffer(&msaa_sample_count); } - if (!surface) { - surface = CreateUnacceleratedImageBufferSurface(); + if (!canvas2d_buffer_) { + canvas2d_buffer_ = CreateUnaccelerated2dBuffer(); } } - if (!surface) - return; - DCHECK(surface->IsValid()); - surface->SetCanvasResourceHost(this); - image_buffer_ = ImageBuffer::Create(std::move(surface)); - did_fail_to_create_image_buffer_ = false; + if (!canvas2d_buffer_ && !webgl_buffer_) + return; + + if (canvas2d_buffer_) + canvas2d_buffer_->SetCanvasResourceHost(this); + + did_fail_to_create_buffer_ = false; UpdateMemoryUsage(); if (Is3d()) { @@ -1119,32 +1115,44 @@ } PaintCanvas* HTMLCanvasElement::DrawingCanvas() { - return GetOrCreateImageBuffer() ? GetImageBuffer()->Canvas() : nullptr; + if (!TryCreateImageBuffer()) + return nullptr; + if (canvas2d_buffer_) + return canvas2d_buffer_->Canvas(); + if (webgl_buffer_) + return webgl_buffer_->Canvas(); + NOTREACHED(); + return nullptr; } void HTMLCanvasElement::DisableDeferral(DisableDeferralReason reason) { - if (GetOrCreateImageBuffer()) - image_buffer_->DisableDeferral(reason); + if (canvas2d_buffer_) + canvas2d_buffer_->DisableDeferral(reason); } PaintCanvas* HTMLCanvasElement::ExistingDrawingCanvas() const { - if (!GetImageBuffer()) - return nullptr; - - return image_buffer_->Canvas(); + if (canvas2d_buffer_) + return canvas2d_buffer_->Canvas(); + if (webgl_buffer_) + return webgl_buffer_->Canvas(); + return nullptr; } -ImageBuffer* HTMLCanvasElement::GetOrCreateImageBuffer() { +bool HTMLCanvasElement::TryCreateImageBuffer() { DCHECK(context_); DCHECK(context_->GetContextType() != CanvasRenderingContext::kContextImageBitmap); - if (!image_buffer_ && !did_fail_to_create_image_buffer_) - CreateImageBuffer(); - return image_buffer_.get(); + if (!HasImageBuffer() && !did_fail_to_create_buffer_) { + CreateImageBufferInternal(nullptr); + if (did_fail_to_create_buffer_ && Is2d() && !Size().IsEmpty()) { + context_->LoseContext(CanvasRenderingContext::kSyntheticLostContext); + } + } + return HasImageBuffer(); } void HTMLCanvasElement::CreateImageBufferUsingSurfaceForTesting( - std::unique_ptr<ImageBufferSurface> surface) { + std::unique_ptr<Canvas2DLayerBridge> surface) { DiscardImageBuffer(); SetIntegralAttribute(widthAttr, surface->Size().Width()); SetIntegralAttribute(heightAttr, surface->Size().Height()); @@ -1180,15 +1188,16 @@ // The concept of SourceDrawingBuffer is valid on only WebGL. if (context_->Is3d()) need_to_update |= context_->PaintRenderingResultsToCanvas(source_buffer); - if (need_to_update && GetOrCreateImageBuffer()) { - copied_image_ = GetImageBuffer()->NewImageSnapshot(hint, snapshot_reason); + if (need_to_update && TryCreateImageBuffer()) { + copied_image_ = NewImageSnapshot(hint, snapshot_reason); UpdateMemoryUsage(); } return copied_image_; } void HTMLCanvasElement::DiscardImageBuffer() { - image_buffer_.reset(); + canvas2d_buffer_.reset(); + webgl_buffer_.reset(); dirty_rect_ = FloatRect(); UpdateMemoryUsage(); } @@ -1236,15 +1245,15 @@ void HTMLCanvasElement::WillDrawImageTo2DContext(CanvasImageSource* source) { if (CanvasHeuristicParameters::kEnableAccelerationToAvoidReadbacks && SharedGpuContext::AllowSoftwareToAcceleratedCanvasUpgrade() && - source->IsAccelerated() && GetOrCreateImageBuffer() && - !GetImageBuffer()->IsAccelerated() && + source->IsAccelerated() && TryCreateImageBuffer() && canvas2d_buffer_ && + !canvas2d_buffer_->IsAccelerated() && ShouldAccelerate(kIgnoreResourceLimitCriteria)) { int msaa_sample_count = 0; - std::unique_ptr<ImageBufferSurface> surface = - CreateAcceleratedImageBufferSurface(&msaa_sample_count); + std::unique_ptr<Canvas2DLayerBridge> surface = + CreateAccelerated2dBuffer(&msaa_sample_count); if (surface) { RestoreCanvasMatrixClipStack(surface->Canvas()); - GetOrCreateImageBuffer()->SetSurface(std::move(surface)); + ReplaceExistingCanvas2DBuffer(std::move(surface)); UpdateMemoryUsage(); SetNeedsCompositingUpdate(); } @@ -1295,16 +1304,16 @@ // use paintRenderingResultsToCanvas instead of getImage in order to keep a // cached copy of the backing in the canvas's ImageBuffer. RenderingContext()->PaintRenderingResultsToCanvas(kBackBuffer); - if (GetImageBuffer()) { - image = GetImageBuffer()->NewImageSnapshot(hint, reason); + if (webgl_buffer_) { + image = webgl_buffer_->NewImageSnapshot(hint, reason); } else { image = CreateTransparentImage(Size()); } } else { if (CanvasHeuristicParameters::kDisableAccelerationToAvoidReadbacks && !RuntimeEnabledFeatures::Canvas2dFixedRenderingModeEnabled() && - hint == kPreferNoAcceleration && GetImageBuffer() && - GetImageBuffer()->IsAccelerated()) { + hint == kPreferNoAcceleration && canvas2d_buffer_ && + canvas2d_buffer_->IsAccelerated()) { DisableAcceleration(); } image = RenderingContext()->GetImage(hint, reason); @@ -1485,22 +1494,27 @@ void HTMLCanvasElement::UpdateMemoryUsage() { int non_gpu_buffer_count = 0; int gpu_buffer_count = 0; - if (image_buffer_) { + if (Is2d() && canvas2d_buffer_) { non_gpu_buffer_count++; - if (image_buffer_->IsAccelerated()) { + if (canvas2d_buffer_->IsAccelerated()) { // The number of internal GPU buffers vary between one (stable // non-displayed state) and three (triple-buffered animations). // Adding 2 is a pessimistic but relevant estimate. // Note: These buffers might be allocated in GPU memory. - gpu_buffer_count = 2; + gpu_buffer_count += 2; } } if (copied_image_) non_gpu_buffer_count++; - if (Is3d()) + if (Is3d()) { + if (webgl_buffer_) { + non_gpu_buffer_count++; + gpu_buffer_count += 2; + } non_gpu_buffer_count += context_->ExternallyAllocatedBufferCountPerPixel(); + } int bytes_per_pixel = ColorParams().BytesPerPixel(); @@ -1541,4 +1555,30 @@ externally_allocated_memory_ = externally_allocated_memory; } +void HTMLCanvasElement::ReplaceExistingCanvas2DBuffer( + std::unique_ptr<Canvas2DLayerBridge> new_buffer) { + if (canvas2d_buffer_) { + scoped_refptr<StaticBitmapImage> image = canvas2d_buffer_->NewImageSnapshot( + kPreferNoAcceleration, kSnapshotReasonPaint); + + // image can be null if alloaction failed in which case we should just + // abort the surface switch to reatain the old surface which is still + // functional. + if (!image) + return; + new_buffer->Canvas()->drawImage(image->PaintImageForCurrentFrame(), 0, 0); + } + canvas2d_buffer_ = std::move(new_buffer); +} + +scoped_refptr<StaticBitmapImage> HTMLCanvasElement::NewImageSnapshot( + AccelerationHint hint, + SnapshotReason reason) { + if (canvas2d_buffer_) + return canvas2d_buffer_->NewImageSnapshot(hint, reason); + if (webgl_buffer_) + return webgl_buffer_->NewImageSnapshot(hint, reason); + return nullptr; +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.h b/third_party/WebKit/Source/core/html/HTMLCanvasElement.h index 0c8e790a..6507104 100644 --- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.h +++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.h
@@ -57,6 +57,8 @@ namespace blink { +class AcceleratedImageBufferSurface; +class Canvas2DLayerBridge; class CanvasColorParams; class CanvasContextCreationAttributes; class CanvasRenderingContext; @@ -66,8 +68,6 @@ class HTMLCanvasElement; class Image; class ImageBitmapOptions; -class ImageBuffer; -class ImageBufferSurface; class IntSize; class @@ -159,16 +159,16 @@ bool Is2d() const; bool IsAnimated2d() const; + Canvas2DLayerBridge* Canvas2DBuffer() { return canvas2d_buffer_.get(); } + AcceleratedImageBufferSurface* WebGLBuffer() { return webgl_buffer_.get(); } + bool HasImageBuffer() { return !!canvas2d_buffer_ || !!webgl_buffer_; } void DiscardImageBuffer() override; - ImageBuffer* GetImageBuffer() const override { return image_buffer_.get(); } - ImageBuffer* GetOrCreateImageBuffer() override; + bool TryCreateImageBuffer(); FontSelector* GetFontSelector() override; bool ShouldBeDirectComposited() const; - void PrepareSurfaceForPaintingIfNeeded(); - const AtomicString ImageSourceURL() const override; InsertionNotificationRequest InsertedInto(ContainerNode*) override; @@ -226,7 +226,7 @@ virtual void TraceWrappers(const ScriptWrappableVisitor*) const; void CreateImageBufferUsingSurfaceForTesting( - std::unique_ptr<ImageBufferSurface>); + std::unique_ptr<Canvas2DLayerBridge>); static void RegisterRenderingContextFactory( std::unique_ptr<CanvasRenderingContextFactory>); @@ -309,13 +309,11 @@ void Reset(); - std::unique_ptr<ImageBufferSurface> CreateWebGLImageBufferSurface(); - std::unique_ptr<ImageBufferSurface> CreateAcceleratedImageBufferSurface( + std::unique_ptr<AcceleratedImageBufferSurface> CreateWebGLBuffer(); + std::unique_ptr<Canvas2DLayerBridge> CreateAccelerated2dBuffer( int* msaa_sample_count); - std::unique_ptr<ImageBufferSurface> CreateUnacceleratedImageBufferSurface(); - void CreateImageBuffer(); - void CreateImageBufferInternal( - std::unique_ptr<ImageBufferSurface> external_surface); + std::unique_ptr<Canvas2DLayerBridge> CreateUnaccelerated2dBuffer(); + void CreateImageBufferInternal(std::unique_ptr<Canvas2DLayerBridge>); void SetSurfaceSize(const IntSize&); @@ -342,11 +340,19 @@ bool origin_clean_; bool needs_unbuffered_input_ = false; - // It prevents HTMLCanvasElement::buffer() from continuously re-attempting to - // allocate an imageBuffer after the first attempt failed. - mutable bool did_fail_to_create_image_buffer_; - bool image_buffer_is_clear_; - std::unique_ptr<ImageBuffer> image_buffer_; + // It prevents HTMLCanvasElement::TryCreateImageBuffer() from continuously + // re-attempting to allocate a Canvas2DLayerBridge (or + // AcceleratedImageBufferSurface) after the first attempt failed. + mutable bool did_fail_to_create_buffer_; + bool buffer_is_clear_; + // Buffers: canvas2d_buffer_ for 2d context and webgl_buffer_ for webgl + // context. + std::unique_ptr<Canvas2DLayerBridge> canvas2d_buffer_; + std::unique_ptr<AcceleratedImageBufferSurface> webgl_buffer_; + void ReplaceExistingCanvas2DBuffer(std::unique_ptr<Canvas2DLayerBridge>); + + scoped_refptr<StaticBitmapImage> NewImageSnapshot(AccelerationHint, + SnapshotReason); // FIXME: This is temporary for platforms that have to copy the image buffer // to render (and for CSSCanvasValue).
diff --git a/third_party/WebKit/Source/core/html/HTMLElement.cpp b/third_party/WebKit/Source/core/html/HTMLElement.cpp index 19c484d..b8bcc95b 100644 --- a/third_party/WebKit/Source/core/html/HTMLElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLElement.cpp
@@ -31,7 +31,7 @@ #include "core/CSSValueKeywords.h" #include "core/css/CSSColorValue.h" #include "core/css/CSSMarkup.h" -#include "core/css/MutableCSSPropertyValueSet.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/css/StyleChangeReason.h" #include "core/dom/DocumentFragment.h" #include "core/dom/ElementShadow.h"
diff --git a/third_party/WebKit/Source/core/html/HTMLHRElement.cpp b/third_party/WebKit/Source/core/html/HTMLHRElement.cpp index 1fb5dbc..0a2bdc508 100644 --- a/third_party/WebKit/Source/core/html/HTMLHRElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLHRElement.cpp
@@ -25,7 +25,7 @@ #include "core/CSSPropertyNames.h" #include "core/CSSValueKeywords.h" #include "core/css/CSSColorValue.h" -#include "core/css/MutableCSSPropertyValueSet.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/html/forms/HTMLOptGroupElement.h" #include "core/html/forms/HTMLSelectElement.h" #include "core/html_names.h"
diff --git a/third_party/WebKit/Source/core/html/HTMLPreElement.cpp b/third_party/WebKit/Source/core/html/HTMLPreElement.cpp index 4a6ee29f..a144c7f7 100644 --- a/third_party/WebKit/Source/core/html/HTMLPreElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLPreElement.cpp
@@ -24,7 +24,7 @@ #include "core/CSSPropertyNames.h" #include "core/CSSValueKeywords.h" -#include "core/css/MutableCSSPropertyValueSet.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/html_names.h" namespace blink {
diff --git a/third_party/WebKit/Source/core/html/HTMLTableElement.cpp b/third_party/WebKit/Source/core/html/HTMLTableElement.cpp index 8e79ac96..1c0264bf2 100644 --- a/third_party/WebKit/Source/core/html/HTMLTableElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLTableElement.cpp
@@ -31,7 +31,7 @@ #include "core/css/CSSIdentifierValue.h" #include "core/css/CSSImageValue.h" #include "core/css/CSSInheritedValue.h" -#include "core/css/MutableCSSPropertyValueSet.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/css/StyleChangeReason.h" #include "core/dom/Attribute.h" #include "core/dom/ElementTraversal.h"
diff --git a/third_party/WebKit/Source/core/html/HTMLTablePartElement.cpp b/third_party/WebKit/Source/core/html/HTMLTablePartElement.cpp index cadfa81..42fc088 100644 --- a/third_party/WebKit/Source/core/html/HTMLTablePartElement.cpp +++ b/third_party/WebKit/Source/core/html/HTMLTablePartElement.cpp
@@ -27,7 +27,7 @@ #include "core/CSSPropertyNames.h" #include "core/CSSValueKeywords.h" #include "core/css/CSSImageValue.h" -#include "core/css/MutableCSSPropertyValueSet.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/dom/Document.h" #include "core/dom/FlatTreeTraversal.h" #include "core/frame/UseCounter.h"
diff --git a/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContextHost.h b/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContextHost.h index f8ee5b7..bbf2254 100644 --- a/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContextHost.h +++ b/third_party/WebKit/Source/core/html/canvas/CanvasRenderingContextHost.h
@@ -13,7 +13,6 @@ #include "platform/bindings/ScriptState.h" #include "platform/geometry/FloatRect.h" #include "platform/geometry/IntSize.h" -#include "platform/graphics/ImageBuffer.h" #include "platform/heap/GarbageCollected.h" namespace blink { @@ -47,8 +46,6 @@ ExceptionState&); virtual void DiscardImageBuffer() = 0; - virtual ImageBuffer* GetImageBuffer() const = 0; - virtual ImageBuffer* GetOrCreateImageBuffer() = 0; // If WebGL1 is disabled by enterprise policy or command line switch. virtual bool IsWebGL1Enabled() const = 0;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp index eb5a428..1b5148c 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorAnimationAgent.cpp
@@ -443,31 +443,34 @@ return Response::OK(); } -static CSSPropertyID g_animation_properties[] = { - CSSPropertyAnimationDelay, CSSPropertyAnimationDirection, - CSSPropertyAnimationDuration, CSSPropertyAnimationFillMode, - CSSPropertyAnimationIterationCount, CSSPropertyAnimationName, - CSSPropertyAnimationTimingFunction}; - -static CSSPropertyID g_transition_properties[] = { - CSSPropertyTransitionDelay, CSSPropertyTransitionDuration, - CSSPropertyTransitionProperty, CSSPropertyTransitionTimingFunction, -}; - String InspectorAnimationAgent::CreateCSSId(blink::Animation& animation) { + static const CSSProperty* g_animation_properties[] = { + &GetCSSPropertyAnimationDelay(), + &GetCSSPropertyAnimationDirection(), + &GetCSSPropertyAnimationDuration(), + &GetCSSPropertyAnimationFillMode(), + &GetCSSPropertyAnimationIterationCount(), + &GetCSSPropertyAnimationName(), + &GetCSSPropertyAnimationTimingFunction(), + }; + static const CSSProperty* g_transition_properties[] = { + &GetCSSPropertyTransitionDelay(), &GetCSSPropertyTransitionDuration(), + &GetCSSPropertyTransitionProperty(), + &GetCSSPropertyTransitionTimingFunction(), + }; String type = id_to_animation_type_.at(String::Number(animation.SequenceNumber())); DCHECK_NE(type, AnimationType::WebAnimation); KeyframeEffectReadOnly* effect = ToKeyframeEffectReadOnly(animation.effect()); - Vector<CSSPropertyID> css_properties; + Vector<const CSSProperty*> css_properties; if (type == AnimationType::CSSAnimation) { - for (CSSPropertyID property : g_animation_properties) + for (const CSSProperty* property : g_animation_properties) css_properties.push_back(property); } else { - for (CSSPropertyID property : g_transition_properties) + for (const CSSProperty* property : g_transition_properties) css_properties.push_back(property); - css_properties.push_back(cssPropertyID(animation.id())); + css_properties.push_back(&CSSProperty::Get(cssPropertyID(animation.id()))); } Element* element = effect->Target(); @@ -477,14 +480,14 @@ CreateDigestor(kHashAlgorithmSha1); AddStringToDigestor(digestor.get(), type); AddStringToDigestor(digestor.get(), animation.id()); - for (CSSPropertyID property : css_properties) { + for (const CSSProperty* property : css_properties) { CSSStyleDeclaration* style = - css_agent_->FindEffectiveDeclaration(property, styles); + css_agent_->FindEffectiveDeclaration(*property, styles); // Ignore inline styles. if (!style || !style->ParentStyleSheet() || !style->parentRule() || style->parentRule()->type() != CSSRule::kStyleRule) continue; - AddStringToDigestor(digestor.get(), getPropertyNameString(property)); + AddStringToDigestor(digestor.get(), property->GetPropertyNameString()); AddStringToDigestor(digestor.get(), css_agent_->StyleSheetId(style->ParentStyleSheet())); AddStringToDigestor(digestor.get(),
diff --git a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp index 6a9c97e..ded791e 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.cpp
@@ -1107,7 +1107,7 @@ continue; (*style)->addItem( protocol::CSS::CSSComputedStyleProperty::create() - .setName(getPropertyNameString(property_id)) + .setName(property_class.GetPropertyNameString()) .setValue(computed_style_info->GetPropertyValue(property_id)) .build()); } @@ -2114,12 +2114,12 @@ } CSSStyleDeclaration* InspectorCSSAgent::FindEffectiveDeclaration( - CSSPropertyID property_id, + const CSSProperty& property_class, const HeapVector<Member<CSSStyleDeclaration>>& styles) { if (!styles.size()) return nullptr; - String longhand = getPropertyNameString(property_id); + String longhand = property_class.GetPropertyNameString(); CSSStyleDeclaration* found_style = nullptr; for (unsigned i = 0; i < styles.size(); ++i) { @@ -2155,8 +2155,9 @@ return Response::Error("Can't edit a node from a non-active document"); CSSPropertyID property_id = cssPropertyID(property_name); + const CSSProperty& property_class = CSSProperty::Get(property_id); CSSStyleDeclaration* style = - FindEffectiveDeclaration(property_id, MatchingStyles(element)); + FindEffectiveDeclaration(property_class, MatchingStyles(element)); if (!style) return Response::Error("Can't find a style to edit"); @@ -2182,10 +2183,11 @@ Vector<StylePropertyShorthand, 4> shorthands; getMatchingShorthandsForLonghand(property_id, &shorthands); - String shorthand = shorthands.size() > 0 - ? getPropertyNameString(shorthands[0].id()) - : String(); - String longhand = getPropertyNameString(property_id); + String shorthand = + shorthands.size() > 0 + ? CSSProperty::Get(shorthands[0].id()).GetPropertyNameString() + : String(); + String longhand = property_class.GetPropertyNameString(); int found_index = -1; Vector<CSSPropertySourceData>& properties = source_data->property_data;
diff --git a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.h b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.h index 91c25262..db3aa0e0 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorCSSAgent.h
@@ -218,7 +218,7 @@ CSSRule*); CSSStyleDeclaration* FindEffectiveDeclaration( - CSSPropertyID, + const CSSProperty&, const HeapVector<Member<CSSStyleDeclaration>>& styles); HeapVector<Member<CSSStyleDeclaration>> MatchingStyles(Element*);
diff --git a/third_party/WebKit/Source/core/inspector/InspectorEmulationAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorEmulationAgent.cpp index 6203e2b..ed6d6dc 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorEmulationAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorEmulationAgent.cpp
@@ -13,6 +13,7 @@ #include "core/page/Page.h" #include "platform/geometry/DoubleRect.h" #include "platform/graphics/Color.h" +#include "platform/scheduler/util/thread_cpu_throttler.h" #include "platform/wtf/Time.h" #include "public/platform/Platform.h" #include "public/platform/WebFloatPoint.h" @@ -34,17 +35,9 @@ static const char kNavigatorPlatform[] = "navigatorPlatform"; } -InspectorEmulationAgent* InspectorEmulationAgent::Create( - WebLocalFrameImpl* web_local_frame_impl, - Client* client) { - return new InspectorEmulationAgent(web_local_frame_impl, client); -} - InspectorEmulationAgent::InspectorEmulationAgent( - WebLocalFrameImpl* web_local_frame_impl, - Client* client) + WebLocalFrameImpl* web_local_frame_impl) : web_local_frame_(web_local_frame_impl), - client_(client), virtual_time_observer_registered_(false) {} InspectorEmulationAgent::~InspectorEmulationAgent() {} @@ -131,8 +124,8 @@ return Response::OK(); } -Response InspectorEmulationAgent::setCPUThrottlingRate(double throttling_rate) { - client_->SetCPUThrottlingRate(throttling_rate); +Response InspectorEmulationAgent::setCPUThrottlingRate(double rate) { + scheduler::ThreadCPUThrottler::GetInstance()->SetThrottlingRate(rate); return Response::OK(); }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorEmulationAgent.h b/third_party/WebKit/Source/core/inspector/InspectorEmulationAgent.h index fbc9a48..87042bf 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorEmulationAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorEmulationAgent.h
@@ -27,14 +27,7 @@ : public InspectorBaseAgent<protocol::Emulation::Metainfo>, public WebViewScheduler::VirtualTimeObserver { public: - class Client { - public: - virtual ~Client() {} - - virtual void SetCPUThrottlingRate(double rate) {} - }; - - static InspectorEmulationAgent* Create(WebLocalFrameImpl*, Client*); + explicit InspectorEmulationAgent(WebLocalFrameImpl*); ~InspectorEmulationAgent() override; // protocol::Dispatcher::EmulationCommandHandler implementation. @@ -80,12 +73,10 @@ void Trace(blink::Visitor*) override; private: - InspectorEmulationAgent(WebLocalFrameImpl*, Client*); WebViewImpl* GetWebViewImpl(); void VirtualTimeBudgetExpired(); Member<WebLocalFrameImpl> web_local_frame_; - Client* client_; bool virtual_time_observer_registered_; DISALLOW_COPY_AND_ASSIGN(InspectorEmulationAgent);
diff --git a/third_party/WebKit/Source/core/inspector/InspectorTracingAgent.cpp b/third_party/WebKit/Source/core/inspector/InspectorTracingAgent.cpp index 14a2f20..5b904c4 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorTracingAgent.cpp +++ b/third_party/WebKit/Source/core/inspector/InspectorTracingAgent.cpp
@@ -75,13 +75,20 @@ instrumenting_agents_->addInspectorTracingAgent(this); state_->setString(TracingAgentState::kSessionId, IdentifiersFactory::CreateIdentifier()); - client_->EnableTracing(categories.fromMaybe(String())); + + // Tracing is already started by DevTools TracingHandler::Start for the + // renderer target in the browser process. It will eventually start tracing + // in the renderer process via IPC. But we still need a redundant enable here + // for EmitMetadataEvents, at which point we are not sure if tracing + // is already started in the renderer process. + TraceEvent::EnableTracing(categories.fromMaybe(String())); + EmitMetadataEvents(); callback->sendSuccess(); } void InspectorTracingAgent::end(std::unique_ptr<EndCallback> callback) { - client_->DisableTracing(); + TraceEvent::DisableTracing(); InnerDisable(); callback->sendSuccess(); }
diff --git a/third_party/WebKit/Source/core/inspector/InspectorTracingAgent.h b/third_party/WebKit/Source/core/inspector/InspectorTracingAgent.h index ade5f89..9858281 100644 --- a/third_party/WebKit/Source/core/inspector/InspectorTracingAgent.h +++ b/third_party/WebKit/Source/core/inspector/InspectorTracingAgent.h
@@ -26,8 +26,6 @@ public: virtual ~Client() {} - virtual void EnableTracing(const String& category_filter) = 0; - virtual void DisableTracing() = 0; virtual void ShowReloadingBlanket() = 0; virtual void HideReloadingBlanket() = 0; };
diff --git a/third_party/WebKit/Source/core/inspector/ThreadDebugger.h b/third_party/WebKit/Source/core/inspector/ThreadDebugger.h index 4d98dac..a9e0118 100644 --- a/third_party/WebKit/Source/core/inspector/ThreadDebugger.h +++ b/third_party/WebKit/Source/core/inspector/ThreadDebugger.h
@@ -23,7 +23,6 @@ class ExecutionContext; class SourceLocation; -// TODO(dgozman): rename this to ThreadInspector (and subclasses). class CORE_EXPORT ThreadDebugger : public v8_inspector::V8InspectorClient, public V8PerIsolateData::Data { public:
diff --git a/third_party/WebKit/Source/core/layout/ScrollbarsTest.cpp b/third_party/WebKit/Source/core/layout/ScrollbarsTest.cpp index 4175577..6a678c6c 100644 --- a/third_party/WebKit/Source/core/layout/ScrollbarsTest.cpp +++ b/third_party/WebKit/Source/core/layout/ScrollbarsTest.cpp
@@ -978,8 +978,8 @@ // Make sure native scrollbar can change by Emulator. // Disable on Android since Android always enable OverlayScrollbar. - -#if defined(OS_ANDROID) +// TODO(https://crbug.com/795645): This test is failing on the ChromeOS bot. +#if defined(OS_ANDROID) || defined(OS_CHROMEOS) TEST_P(ScrollbarsTest, DISABLED_NativeScrollbarChangeToMobileByEmulator) { #else TEST_P(ScrollbarsTest, NativeScrollbarChangeToMobileByEmulator) {
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_break_token.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_break_token.cc index c9b3704..5576a52 100644 --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_break_token.cc +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_break_token.cc
@@ -18,16 +18,15 @@ item_index_(item_index), text_offset_(text_offset), is_forced_break_(is_forced_break), - state_stack_(std::move(state_stack)) { - // Use nullptr for the initial layout, rather than (0, 0) break token. - DCHECK(item_index || text_offset); -} + ignore_floats_(false), + state_stack_(std::move(state_stack)) {} NGInlineBreakToken::NGInlineBreakToken(NGLayoutInputNode node) : NGBreakToken(kInlineBreakToken, kFinished, node), item_index_(0), text_offset_(0), is_forced_break_(false), + ignore_floats_(false), state_stack_(nullptr) {} NGInlineBreakToken::~NGInlineBreakToken() {}
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_break_token.h b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_break_token.h index 4ff1cf6..38d2535 100644 --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_break_token.h +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_break_token.h
@@ -56,6 +56,15 @@ return *state_stack_; } + // When a previously laid out line box didn't fit in the current + // fragmentainer, and we have to lay it out again in the next fragmentainer, + // we need to skip floats associated with that line. The parent block layout + // algorithm will take care of any floats that broke and need to be resumed in + // the next fragmentainer. Dealing with them as part of line layout as well + // would result in duplicate fragments for the floats. + void SetIgnoreFloats() { ignore_floats_ = true; } + bool IgnoreFloats() const { return ignore_floats_; } + #ifndef NDEBUG String ToString() const override; #endif // NDEBUG @@ -72,6 +81,7 @@ unsigned item_index_; unsigned text_offset_; unsigned is_forced_break_ : 1; + unsigned ignore_floats_ : 1; std::unique_ptr<const NGInlineLayoutStateStack> state_stack_; };
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc index 6da3d8c8..3771b93 100644 --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_layout_algorithm.cc
@@ -702,6 +702,11 @@ DCHECK(container_builder_.BfcOffset() || ConstraintSpace().FloatsBfcOffset()) << "The parent BFC offset should be known here"; + if (BreakToken() && BreakToken()->IgnoreFloats()) { + unpositioned_floats_.clear(); + return; + } + NGBfcOffset bfc_offset = container_builder_.BfcOffset() ? container_builder_.BfcOffset().value() : ConstraintSpace().FloatsBfcOffset().value();
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc index fc1b573..26b7039 100644 --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_node.cc
@@ -35,6 +35,7 @@ #include "core/layout/ng/ng_box_fragment.h" #include "core/layout/ng/ng_constraint_space_builder.h" #include "core/layout/ng/ng_fragment_builder.h" +#include "core/layout/ng/ng_fragmentation_utils.h" #include "core/layout/ng/ng_layout_result.h" #include "core/layout/ng/ng_length_utils.h" #include "core/layout/ng/ng_physical_box_fragment.h" @@ -366,6 +367,7 @@ const Vector<unsigned, 32>& text_offsets, const NGConstraintSpace& constraint_space, const NGPhysicalBoxFragment& box_fragment, + LayoutUnit extra_block_offset, LayoutBlockFlow& block_flow, LineInfo& line_info) { FontBaseline baseline_type = @@ -389,6 +391,7 @@ physical_line_box.Offset().ConvertToLogical( constraint_space.GetWritingMode(), TextDirection::kLtr, box_fragment.Size(), physical_line_box.Size()); + line_box_offset.block_offset += extra_block_offset; // Create a BidiRunList for this line. CreateBidiRuns(&bidi_runs, physical_line_box.Children(), constraint_space, @@ -785,25 +788,35 @@ descend_into_fragmentainers = true; } - block_flow->DeleteLineBoxTree(); + NGPhysicalBoxFragment* box_fragment = + ToNGPhysicalBoxFragment(layout_result.PhysicalFragment().get()); + if (IsFirstFragment(constraint_space, *box_fragment)) + block_flow->DeleteLineBoxTree(); const Vector<NGInlineItem>& items = Data().items_; Vector<unsigned, 32> text_offsets(items.size()); GetLayoutTextOffsets(&text_offsets); LineInfo line_info; - NGPhysicalBoxFragment* box_fragment = - ToNGPhysicalBoxFragment(layout_result.PhysicalFragment().get()); if (descend_into_fragmentainers) { + LayoutUnit extra_block_offset; for (const auto& child : box_fragment->Children()) { DCHECK(child->IsBox()); const auto& fragmentainer = ToNGPhysicalBoxFragment(*child.get()); PlaceLineBoxChildren(items, text_offsets, constraint_space, fragmentainer, - *block_flow, line_info); + extra_block_offset, *block_flow, line_info); + extra_block_offset = + ToNGBlockBreakToken(fragmentainer.BreakToken())->UsedBlockSize(); } } else { + LayoutUnit extra_block_offset; + if (constraint_space.HasBlockFragmentation()) { + extra_block_offset = + PreviouslyUsedBlockSpace(constraint_space, *box_fragment); + } + PlaceLineBoxChildren(items, text_offsets, constraint_space, *box_fragment, - *block_flow, line_info); + extra_block_offset, *block_flow, line_info); } }
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc index e72ab18a..02eaa68 100644 --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.cc
@@ -44,6 +44,7 @@ offset_ = break_token->TextOffset(); previous_line_had_forced_break_ = break_token->IsForcedBreak(); node.AssertOffset(item_index_, offset_); + ignore_floats_ = break_token->IgnoreFloats(); } } @@ -482,7 +483,11 @@ // twice. // Ideally rewind can take floats out of floats list, but the difference is // sutble compared to the complexity. - if (item_index_ < handled_floats_end_item_index_) { + // + // Additionally, we need to skip floats if we're retrying a line after a + // fragmentainer break. In that case the floats associated with this line will + // already have been processed. + if (item_index_ < handled_floats_end_item_index_ || ignore_floats_) { MoveToNextOf(item); return ComputeIsBreakableAfter(item_result); }
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.h b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.h index cfa3db0e..ffb88a7 100644 --- a/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.h +++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_line_breaker.h
@@ -181,6 +181,8 @@ // quirks. // https://quirks.spec.whatwg.org/#the-line-height-calculation-quirk bool in_line_height_quirks_mode_ = false; + + bool ignore_floats_ = false; }; } // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.cc b/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.cc index 922b1e6..ccd59bf0 100644 --- a/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.cc +++ b/third_party/WebKit/Source/core/layout/ng/layout_ng_block_flow.cc
@@ -38,14 +38,6 @@ scoped_refptr<NGLayoutResult> result = NGBlockNode(this).Layout(*constraint_space); - // We need to update our margins as these are calculated once and stored in - // LayoutBox::margin_box_outsets_. Typically this happens within - // UpdateLogicalWidth and UpdateLogicalHeight. - // - // This primarily fixes cases where we are embedded inside another layout, - // for example LayoutView, LayoutFlexibleBox, etc. - UpdateMargins(*constraint_space); - for (NGOutOfFlowPositionedDescendant descendant : result->OutOfFlowPositionedDescendants()) descendant.node.UseOldOutOfFlowPositioning();
diff --git a/third_party/WebKit/Source/core/layout/ng/layout_ng_mixin.cc b/third_party/WebKit/Source/core/layout/ng/layout_ng_mixin.cc index 457a51d9..4a4f47a9 100644 --- a/third_party/WebKit/Source/core/layout/ng/layout_ng_mixin.cc +++ b/third_party/WebKit/Source/core/layout/ng/layout_ng_mixin.cc
@@ -158,12 +158,6 @@ } template <typename Base> -void LayoutNGMixin<Base>::UpdateMargins( - const NGConstraintSpace& constraint_space) { - Base::SetMargin(ComputePhysicalMargins(constraint_space, Base::StyleRef())); -} - -template <typename Base> bool LayoutNGMixin<Base>::NodeAtPoint( HitTestResult& result, const HitTestLocation& location_in_container,
diff --git a/third_party/WebKit/Source/core/layout/ng/layout_ng_mixin.h b/third_party/WebKit/Source/core/layout/ng/layout_ng_mixin.h index f064339..a9d1922a 100644 --- a/third_party/WebKit/Source/core/layout/ng/layout_ng_mixin.h +++ b/third_party/WebKit/Source/core/layout/ng/layout_ng_mixin.h
@@ -75,8 +75,6 @@ const NGBaseline* FragmentBaseline(NGBaselineAlgorithmType) const; - void UpdateMargins(const NGConstraintSpace&); - std::unique_ptr<NGInlineNodeData> ng_inline_node_data_; scoped_refptr<NGLayoutResult> cached_result_;
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_child_iterator.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_child_iterator.cc index e0947557..57ca240f 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_block_child_iterator.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_block_child_iterator.cc
@@ -5,6 +5,7 @@ #include "core/layout/ng/ng_block_child_iterator.h" #include "core/layout/ng/ng_block_break_token.h" +#include "core/layout/ng/ng_block_node.h" #include "core/layout/ng/ng_layout_input_node.h" namespace blink { @@ -26,6 +27,9 @@ } return; } + auto first_node_child = ToNGBlockNode(break_token->InputNode()).FirstChild(); + resuming_at_inline_formatting_context_ = + first_node_child && first_node_child.IsInline(); child_ = child_break_tokens[0]->InputNode(); } @@ -50,6 +54,22 @@ // [1] https://drafts.csswg.org/css-break/#parallel-flows const auto& child_break_tokens = break_token_->ChildBreakTokens(); + if (resuming_at_inline_formatting_context_) { + // When resuming inside an inline formatting context, just process the + // break tokens. There'll be any number of break tokens for broken floats, + // followed by at most one break token for the actual inline formatting + // context where we had to give up in the previous fragmentainer. The node + // structure will not be of any help at all, since the break tokens will + // be associated with nodes that are not siblings. + while (child_token_idx_ < child_break_tokens.size()) { + const auto& token = child_break_tokens[child_token_idx_]; + child_token_idx_++; + if (!token->IsFinished()) + return Entry(token->InputNode(), token.get()); + } + return Entry(nullptr, nullptr); + } + do { // Early exit if we've exhausted our child break tokens. if (child_token_idx_ >= child_break_tokens.size())
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_child_iterator.h b/third_party/WebKit/Source/core/layout/ng/ng_block_child_iterator.h index d821348..653bb14 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_block_child_iterator.h +++ b/third_party/WebKit/Source/core/layout/ng/ng_block_child_iterator.h
@@ -40,6 +40,8 @@ // An index into break_token_'s ChildBreakTokens() vector. Used for keeping // track of the next child break token to inspect. size_t child_token_idx_; + + bool resuming_at_inline_formatting_context_ = false; }; struct NGBlockChildIterator::Entry {
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc index 313c4643..68a996a 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm.cc
@@ -493,11 +493,8 @@ // We only finalize for fragmentation if the fragment has a BFC offset. This // may occur with a zero block size fragment. We need to know the BFC offset // to determine where the fragmentation line is relative to us. - // TODO(ikilpatrick): Skip this step if we are inside an inline formatting - // context at the moment. This is wrong, and needs work to correct it. if (container_builder_.BfcOffset() && - ConstraintSpace().HasBlockFragmentation() && - !Node().FirstChild().IsInline()) + ConstraintSpace().HasBlockFragmentation()) FinalizeForFragmentation(); // Only layout absolute and fixed children if we aren't going to revisit this @@ -1272,14 +1269,16 @@ if (space_left >= ConstraintSpace().FragmentainerBlockSize()) return false; + if (child.IsInline()) { + NGFragment fragment(ConstraintSpace().GetWritingMode(), physical_fragment); + return fragment.BlockSize() > space_left; + } + // If the block offset is past the fragmentainer boundary (or exactly at the // boundary), no part of the fragment is going to fit in the current // fragmentainer. Fragments may be pushed past the fragmentainer boundary by // margins. - // TODO(mstensho): The inline check here shouldn't be necessary, but - // it's needed as long as we don't support breaking between line - // boxes. - if (space_left <= LayoutUnit() && !child.IsInline()) + if (space_left <= LayoutUnit()) return true; const auto* token = physical_fragment.BreakToken(); @@ -1376,19 +1375,20 @@ space_builder.SetUnpositionedFloats(unpositioned_floats_); } + WritingMode writing_mode; if (child.IsInline()) { - // TODO(kojii): Setup space_builder appropriately for inline child. space_builder.SetClearanceOffset(ConstraintSpace().ClearanceOffset()); - return space_builder.ToConstraintSpace(Style().GetWritingMode()); + writing_mode = Style().GetWritingMode(); + } else { + const ComputedStyle& child_style = child.Style(); + space_builder + .SetClearanceOffset( + exclusion_space_->ClearanceOffset(child_style.Clear())) + .SetIsShrinkToFit(ShouldShrinkToFit(Style(), child_style)) + .SetTextDirection(child_style.Direction()); + writing_mode = child_style.GetWritingMode(); } - const ComputedStyle& child_style = child.Style(); - space_builder - .SetClearanceOffset( - exclusion_space_->ClearanceOffset(child_style.Clear())) - .SetIsShrinkToFit(ShouldShrinkToFit(Style(), child_style)) - .SetTextDirection(child_style.Direction()); - LayoutUnit space_available; if (ConstraintSpace().HasBlockFragmentation()) { space_available = ConstraintSpace().FragmentainerSpaceAtBfcStart(); @@ -1405,7 +1405,7 @@ space_builder.SetFragmentationType( ConstraintSpace().BlockFragmentationType()); - return space_builder.ToConstraintSpace(child_style.GetWritingMode()); + return space_builder.ToConstraintSpace(writing_mode); } // Add a baseline from a child box fragment.
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_column_layout_algorithm_test.cc b/third_party/WebKit/Source/core/layout/ng/ng_column_layout_algorithm_test.cc index c9f3198..14b737c 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_column_layout_algorithm_test.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_column_layout_algorithm_test.cc
@@ -937,6 +937,384 @@ EXPECT_EQ(expectation, dump); } +TEST_F(NGColumnLayoutAlgorithmTest, LinesInMulticolExtraSpace) { + SetBodyInnerHTML(R"HTML( + <style> + #parent { + columns: 3; + column-fill: auto; + column-gap: 10px; + width: 320px; + height: 50px; + line-height: 20px; + orphans: 1; + widows: 1; + } + </style> + <div id="container"> + <div id="parent"> + <br> + <br> + <br> + <br> + </div> + </div> + )HTML"); + + String dump = DumpFragmentTree(GetElementById("container")); + String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. + offset:unplaced size:1000x50 + offset:0,0 size:320x50 + offset:0,0 size:100x50 + offset:0,0 size:0x20 + offset:0,9 size:0x1 + offset:0,20 size:0x20 + offset:0,9 size:0x1 + offset:110,0 size:100x40 + offset:0,0 size:0x20 + offset:0,9 size:0x1 + offset:0,20 size:0x20 + offset:0,9 size:0x1 +)DUMP"; + EXPECT_EQ(expectation, dump); +} + +TEST_F(NGColumnLayoutAlgorithmTest, LinesInMulticolExactFit) { + SetBodyInnerHTML(R"HTML( + <style> + #parent { + columns: 3; + column-fill: auto; + column-gap: 10px; + width: 320px; + height: 40px; + line-height: 20px; + orphans: 1; + widows: 1; + } + </style> + <div id="container"> + <div id="parent"> + <br> + <br> + <br> + <br> + </div> + </div> + )HTML"); + + String dump = DumpFragmentTree(GetElementById("container")); + String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. + offset:unplaced size:1000x40 + offset:0,0 size:320x40 + offset:0,0 size:100x40 + offset:0,0 size:0x20 + offset:0,9 size:0x1 + offset:0,20 size:0x20 + offset:0,9 size:0x1 + offset:110,0 size:100x40 + offset:0,0 size:0x20 + offset:0,9 size:0x1 + offset:0,20 size:0x20 + offset:0,9 size:0x1 +)DUMP"; + EXPECT_EQ(expectation, dump); +} + +TEST_F(NGColumnLayoutAlgorithmTest, LinesInMulticolChildExtraSpace) { + SetBodyInnerHTML(R"HTML( + <style> + #parent { + columns: 3; + column-fill: auto; + column-gap: 10px; + width: 320px; + height: 50px; + line-height: 20px; + orphans: 1; + widows: 1; + } + </style> + <div id="container"> + <div id="parent"> + <div style="width:77px;"> + <br> + <br> + <br> + <br> + </div> + </div> + </div> + )HTML"); + + String dump = DumpFragmentTree(GetElementById("container")); + String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. + offset:unplaced size:1000x50 + offset:0,0 size:320x50 + offset:0,0 size:100x50 + offset:0,0 size:77x50 + offset:0,0 size:0x20 + offset:0,9 size:0x1 + offset:0,20 size:0x20 + offset:0,9 size:0x1 + offset:110,0 size:100x40 + offset:0,0 size:77x40 + offset:0,0 size:0x20 + offset:0,9 size:0x1 + offset:0,20 size:0x20 + offset:0,9 size:0x1 +)DUMP"; + EXPECT_EQ(expectation, dump); +} + +TEST_F(NGColumnLayoutAlgorithmTest, LinesInMulticolChildExactFit) { + SetBodyInnerHTML(R"HTML( + <style> + #parent { + columns: 3; + column-fill: auto; + column-gap: 10px; + width: 320px; + height: 40px; + line-height: 20px; + orphans: 1; + widows: 1; + } + </style> + <div id="container"> + <div id="parent"> + <div style="width:77px;"> + <br> + <br> + <br> + <br> + </div> + </div> + </div> + )HTML"); + + String dump = DumpFragmentTree(GetElementById("container")); + String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. + offset:unplaced size:1000x40 + offset:0,0 size:320x40 + offset:0,0 size:100x40 + offset:0,0 size:77x40 + offset:0,0 size:0x20 + offset:0,9 size:0x1 + offset:0,20 size:0x20 + offset:0,9 size:0x1 + offset:110,0 size:100x40 + offset:0,0 size:77x40 + offset:0,0 size:0x20 + offset:0,9 size:0x1 + offset:0,20 size:0x20 + offset:0,9 size:0x1 +)DUMP"; + EXPECT_EQ(expectation, dump); +} + +TEST_F(NGColumnLayoutAlgorithmTest, LinesInMulticolChildNoSpaceForFirst) { + SetBodyInnerHTML(R"HTML( + <style> + #parent { + columns: 3; + column-fill: auto; + column-gap: 10px; + width: 320px; + height: 50px; + line-height: 20px; + orphans: 1; + widows: 1; + } + </style> + <div id="container"> + <div id="parent"> + <div style="height:50px;"></div> + <div style="width:77px;"> + <br> + <br> + <br> + </div> + </div> + </div> + )HTML"); + + String dump = DumpFragmentTree(GetElementById("container")); + String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. + offset:unplaced size:1000x50 + offset:0,0 size:320x50 + offset:0,0 size:100x50 + offset:0,0 size:100x50 + offset:110,0 size:100x50 + offset:0,0 size:77x50 + offset:0,0 size:0x20 + offset:0,9 size:0x1 + offset:0,20 size:0x20 + offset:0,9 size:0x1 + offset:220,0 size:100x20 + offset:0,0 size:77x20 + offset:0,0 size:0x20 + offset:0,9 size:0x1 +)DUMP"; + EXPECT_EQ(expectation, dump); +} + +TEST_F(NGColumnLayoutAlgorithmTest, + LinesInMulticolChildInsufficientSpaceForFirst) { + SetBodyInnerHTML(R"HTML( + <style> + #parent { + columns: 3; + column-fill: auto; + column-gap: 10px; + width: 320px; + height: 50px; + line-height: 20px; + orphans: 1; + widows: 1; + } + </style> + <div id="container"> + <div id="parent"> + <div style="height:40px;"></div> + <div style="width:77px;"> + <br> + <br> + <br> + </div> + </div> + </div> + )HTML"); + + // TODO(mstensho): There's a bug here. The second child block shouldn't create + // a fragment in the first column, because there's no break opportunity + // between that block and its first line box child. The second child block + // should therefore be pushed to the second column. In other words, the + // fragment "offset:0,40 size:77x10" below shouldn't exist. + String dump = DumpFragmentTree(GetElementById("container")); + String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. + offset:unplaced size:1000x50 + offset:0,0 size:320x50 + offset:0,0 size:100x50 + offset:0,0 size:100x40 + offset:0,40 size:77x10 + offset:110,0 size:100x50 + offset:0,0 size:77x50 + offset:0,0 size:0x20 + offset:0,9 size:0x1 + offset:0,20 size:0x20 + offset:0,9 size:0x1 + offset:220,0 size:100x20 + offset:0,0 size:77x20 + offset:0,0 size:0x20 + offset:0,9 size:0x1 +)DUMP"; + EXPECT_EQ(expectation, dump); +} + +TEST_F(NGColumnLayoutAlgorithmTest, LinesAndFloatsMulticol) { + SetBodyInnerHTML(R"HTML( + <style> + #parent { + columns: 3; + column-fill: auto; + column-gap: 10px; + width: 320px; + height: 70px; + line-height: 20px; + orphans: 1; + widows: 1; + } + </style> + <div id="container"> + <div id="parent"> + <br> + <div style="float:left; width:10px; height:120px;"></div> + <br> + <div style="float:left; width:11px; height:120px;"></div> + <br> + <br> + <br> + </div> + </div> + )HTML"); + + String dump = DumpFragmentTree(GetElementById("container")); + String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. + offset:unplaced size:1000x70 + offset:0,0 size:320x70 + offset:0,0 size:100x70 + offset:0,0 size:0x20 + offset:0,9 size:0x1 + offset:0,20 size:10x50 + offset:10,20 size:0x20 + offset:0,9 size:0x1 + offset:10,40 size:11x30 + offset:21,40 size:0x20 + offset:0,9 size:0x1 + offset:110,0 size:100x70 + offset:0,0 size:10x70 + offset:10,0 size:11x70 + offset:21,0 size:0x20 + offset:0,9 size:0x1 + offset:21,20 size:0x20 + offset:0,9 size:0x1 + offset:220,0 size:100x20 + offset:0,0 size:11x20 +)DUMP"; + EXPECT_EQ(expectation, dump); +} + +TEST_F(NGColumnLayoutAlgorithmTest, FloatBelowLastLineInColumn) { + SetBodyInnerHTML(R"HTML( + <style> + #parent { + columns: 3; + column-fill: auto; + column-gap: 10px; + width: 320px; + height: 70px; + line-height: 20px; + orphans: 1; + widows: 1; + } + </style> + <div id="container"> + <div id="parent"> + <br> + <br> + <br> + <div style="float:left; width:11px; height:120px;"></div> + <br> + <br> + </div> + </div> + )HTML"); + + String dump = DumpFragmentTree(GetElementById("container")); + String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. + offset:unplaced size:1000x70 + offset:0,0 size:320x70 + offset:0,0 size:100x70 + offset:0,0 size:0x20 + offset:0,9 size:0x1 + offset:0,20 size:0x20 + offset:0,9 size:0x1 + offset:0,40 size:0x20 + offset:0,9 size:0x1 + offset:0,60 size:11x10 + offset:110,0 size:100x70 + offset:0,0 size:11x70 + offset:11,0 size:0x20 + offset:0,9 size:0x1 + offset:11,20 size:0x20 + offset:0,9 size:0x1 + offset:220,0 size:100x40 + offset:0,0 size:11x40 +)DUMP"; + EXPECT_EQ(expectation, dump); +} + TEST_F(NGColumnLayoutAlgorithmTest, BorderAndPadding) { SetBodyInnerHTML(R"HTML( <style>
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc index 43ff7d55..dbfac9ad 100644 --- a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc +++ b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc
@@ -5,7 +5,9 @@ #include "core/layout/ng/ng_fragment_builder.h" #include "core/layout/LayoutObject.h" +#include "core/layout/ng/inline/ng_inline_break_token.h" #include "core/layout/ng/inline/ng_inline_fragment_iterator.h" +#include "core/layout/ng/inline/ng_inline_node.h" #include "core/layout/ng/inline/ng_physical_line_box_fragment.h" #include "core/layout/ng/ng_block_break_token.h" #include "core/layout/ng/ng_block_node.h" @@ -77,6 +79,19 @@ NGFragmentBuilder& NGFragmentBuilder::AddBreakBeforeChild( NGLayoutInputNode child) { + if (child.IsInline()) { + if (last_inline_break_token_) { + // We need to resume at this inline location in the next fragmentainer, + // but broken floats, which are resumed and positioned by the parent block + // layout algorithm, need to be ignored by the inline layout algorithm. + ToNGInlineBreakToken(last_inline_break_token_.get())->SetIgnoreFloats(); + } else { + last_inline_break_token_ = NGInlineBreakToken::Create( + ToNGInlineNode(child), 0, 0, false, + std::make_unique<NGInlineLayoutStateStack>()); + } + return *this; + } // TODO(mstensho): Come up with a more intuitive way of creating an unfinished // break token. We currently need to pass a Vector here, just to end up in the // right NGBlockBreakToken constructor - the one that sets the token as
diff --git a/third_party/WebKit/Source/core/loader/ProgrammaticScrollTest.cpp b/third_party/WebKit/Source/core/loader/ProgrammaticScrollTest.cpp index cecf9c8..65aea64 100644 --- a/third_party/WebKit/Source/core/loader/ProgrammaticScrollTest.cpp +++ b/third_party/WebKit/Source/core/loader/ProgrammaticScrollTest.cpp
@@ -8,6 +8,9 @@ #include "core/frame/WebLocalFrameImpl.h" #include "core/loader/DocumentLoader.h" #include "core/loader/FrameLoader.h" +#include "core/testing/sim/SimDisplayItemList.h" +#include "core/testing/sim/SimRequest.h" +#include "core/testing/sim/SimTest.h" #include "platform/testing/URLTestHelpers.h" #include "platform/testing/UnitTestHelpers.h" #include "public/platform/Platform.h" @@ -104,4 +107,52 @@ EXPECT_EQ(400, web_view->MainFrameImpl()->GetScrollOffset().height); } +class ProgrammaticScrollSimTest : public ::testing::WithParamInterface<bool>, + private ScopedRootLayerScrollingForTest, + public SimTest { + public: + ProgrammaticScrollSimTest() : ScopedRootLayerScrollingForTest(GetParam()) {} +}; + +INSTANTIATE_TEST_CASE_P(All, ProgrammaticScrollSimTest, ::testing::Bool()); + +TEST_P(ProgrammaticScrollSimTest, NavigateToHash) { + WebView().Resize(WebSize(800, 600)); + SimRequest main_resource("https://example.com/test.html#target", "text/html"); + SimRequest css_resource("https://example.com/test.css", "text/css"); + + LoadURL("https://example.com/test.html#target"); + + // Finish loading the main document before the stylesheet is loaded so that + // rendering is blocked when parsing finishes. This will delay closing the + // document until the load event. + main_resource.Start(); + main_resource.Write( + "<!DOCTYPE html><link id=link rel=stylesheet href=test.css>"); + css_resource.Start(); + main_resource.Write(R"HTML( + <style> + body { + height: 4000px; + } + h2 { + position: absolute; + top: 3000px; + } + </style> + <h2 id="target">Target</h2> + )HTML"); + main_resource.Finish(); + css_resource.Complete(); + Compositor().BeginFrame(); + + // Run pending tasks to fire the load event and close the document. This + // should cause the document to scroll to the hash. + testing::RunPendingTasks(); + + ScrollableArea* layout_viewport = + GetDocument().View()->LayoutViewportScrollableArea(); + EXPECT_EQ(3001, layout_viewport->GetScrollOffset().Height()); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.cpp b/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.cpp index ad449521..670c7ce 100644 --- a/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.cpp +++ b/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.cpp
@@ -26,6 +26,7 @@ #include "platform/graphics/UnacceleratedImageBufferSurface.h" #include "platform/graphics/gpu/AcceleratedImageBufferSurface.h" #include "platform/graphics/gpu/SharedGpuContext.h" +#include "platform/graphics/skia/SkiaUtils.h" #include "platform/image-encoders/ImageEncoderUtils.h" #include "platform/instrumentation/tracing/TraceEvent.h" #include "platform/wtf/MathExtras.h" @@ -219,7 +220,7 @@ bool OffscreenCanvas::IsPaintable() const { if (!context_) - return ImageBuffer::CanCreateImageBuffer(size_); + return IsValidImageSize(size_); return context_->IsPaintable() && size_.Width() && size_.Height(); }
diff --git a/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.h b/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.h index baa09bd..c1f653a2 100644 --- a/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.h +++ b/third_party/WebKit/Source/core/offscreencanvas/OffscreenCanvas.h
@@ -24,6 +24,7 @@ class CanvasContextCreationAttributes; class ImageBitmap; +class ImageBuffer; class OffscreenCanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContext; typedef OffscreenCanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContext @@ -87,7 +88,7 @@ void DiscardImageBuffer() override; ImageBuffer* GetImageBuffer() const { return image_buffer_.get(); } - ImageBuffer* GetOrCreateImageBuffer() override; + ImageBuffer* GetOrCreateImageBuffer(); void SetFrameSinkId(uint32_t client_id, uint32_t sink_id) { client_id_ = client_id;
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp b/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp index 432eed0..25f2082 100644 --- a/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp +++ b/third_party/WebKit/Source/core/paint/PaintLayerClipperTest.cpp
@@ -204,7 +204,12 @@ EXPECT_EQ(LayoutRect(0, 0, 500, 500), layer_bounds); } +// TODO(https://crbug.com/795645): This test is failing on the ChromeOS bot. +#if defined(OS_CHROMEOS) +TEST_F(PaintLayerClipperTest, DISABLED_ControlClipSelect) { +#else TEST_F(PaintLayerClipperTest, ControlClipSelect) { +#endif SetBodyInnerHTML(R"HTML( <select id='target' style='position: relative; width: 100px; background: none; border: none; padding: 0px 15px 0px 5px;'>
diff --git a/third_party/WebKit/Source/core/style/ComputedStyle.h b/third_party/WebKit/Source/core/style/ComputedStyle.h index d2cb9756..900753764 100644 --- a/third_party/WebKit/Source/core/style/ComputedStyle.h +++ b/third_party/WebKit/Source/core/style/ComputedStyle.h
@@ -403,8 +403,6 @@ void SetBorderImageOutset(const BorderImageLengthBox&); // Border width properties. - // TODO(nainar): Move all fixed point logic to a separate class. - // border-top-width float BorderTopWidth() const { if (BorderTopStyle() == EBorderStyle::kNone || BorderTopStyle() == EBorderStyle::kHidden)
diff --git a/third_party/WebKit/Source/core/style/stylerecalc.md b/third_party/WebKit/Source/core/style/stylerecalc.md index 468713f..9eebf42 100644 --- a/third_party/WebKit/Source/core/style/stylerecalc.md +++ b/third_party/WebKit/Source/core/style/stylerecalc.md
@@ -1,5 +1,5 @@ This Markdown file intends to demystify some of the StyleRecalc process: -TODO(nainar): Add more details about the StyleRecalc process here. +TODO(crbug.com/795634): Add more details about the StyleRecalc process here. ## Different StyleRecalc states
diff --git a/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp b/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp index 7c00d47a..ae75425 100644 --- a/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp +++ b/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp
@@ -23,7 +23,7 @@ #include "core/svg/SVGAnimateElement.h" #include "core/css/CSSComputedStyleDeclaration.h" -#include "core/css/MutableCSSPropertyValueSet.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/css/StyleChangeReason.h" #include "core/dom/Document.h" #include "core/dom/QualifiedName.h"
diff --git a/third_party/WebKit/Source/core/svg/SVGElementRareData.cpp b/third_party/WebKit/Source/core/svg/SVGElementRareData.cpp index 552136d..096e689 100644 --- a/third_party/WebKit/Source/core/svg/SVGElementRareData.cpp +++ b/third_party/WebKit/Source/core/svg/SVGElementRareData.cpp
@@ -4,7 +4,6 @@ #include "core/svg/SVGElementRareData.h" -#include "core/css/MutableCSSPropertyValueSet.h" #include "core/css/resolver/StyleResolver.h" #include "core/dom/Document.h" #include "core/svg/SVGElementProxy.h"
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp index e6faaf1..cdadc62 100644 --- a/third_party/WebKit/Source/core/testing/Internals.cpp +++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -41,6 +41,7 @@ #include "core/animation/DocumentTimeline.h" #include "core/css/SelectRuleFeatureSet.h" #include "core/css/StyleEngine.h" +#include "core/css/properties/CSSUnresolvedProperty.h" #include "core/dom/DOMNodeIds.h" #include "core/dom/DOMStringList.h" #include "core/dom/Document.h" @@ -3424,8 +3425,9 @@ Vector<String> result; for (int id = firstCSSProperty; id <= lastCSSProperty; ++id) { CSSPropertyID property = static_cast<CSSPropertyID>(id); - if (CSSProperty::Get(property).IsLonghand()) { - result.push_back(getPropertyNameString(property)); + const CSSProperty& property_class = CSSProperty::Get(property); + if (property_class.IsLonghand()) { + result.push_back(property_class.GetPropertyNameString()); } } return result; @@ -3435,8 +3437,9 @@ Vector<String> result; for (int id = firstCSSProperty; id <= lastCSSProperty; ++id) { CSSPropertyID property = static_cast<CSSPropertyID>(id); - if (CSSProperty::Get(property).IsShorthand()) { - result.push_back(getPropertyNameString(property)); + const CSSProperty& property_class = CSSProperty::Get(property); + if (property_class.IsShorthand()) { + result.push_back(property_class.GetPropertyNameString()); } } return result; @@ -3446,7 +3449,8 @@ Vector<String> result; for (CSSPropertyID alias : kCSSPropertyAliasList) { DCHECK(isPropertyAlias(alias)); - result.push_back(getPropertyNameString(alias)); + result.push_back(CSSUnresolvedProperty::GetAliasProperty(alias) + ->GetPropertyNameString()); } return result; }
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp index 98fe02a4..b6d41a3 100644 --- a/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp +++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerMessagingProxy.cpp
@@ -58,12 +58,14 @@ // TODO(nhiroki): Move ReleaseWorkerClients() to DedicatedWorker for cleanup. creation_params->worker_clients = ReleaseWorkerClients(); - // TODO(nhiroki): Support module scripts (https://crbug.com/680046). - DCHECK_EQ("classic", options.type()); InitializeWorkerThread( std::move(creation_params), - CreateBackingThreadStartupData(ToIsolate(GetExecutionContext())), - script_url, stack_id, source_code); + CreateBackingThreadStartupData(ToIsolate(GetExecutionContext()))); + + // TODO(nhiroki): Support module scripts (https://crbug.com/680046). + DCHECK_EQ("classic", options.type()); + GetWorkerThread()->EvaluateClassicScript( + script_url, source_code, nullptr /* cached_meta_data */, stack_id); // Post all queued tasks to the worker. for (auto& queued_task : queued_early_tasks_) {
diff --git a/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp b/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp index c77d173..4d4cb8e 100644 --- a/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp +++ b/third_party/WebKit/Source/core/workers/DedicatedWorkerTest.cpp
@@ -137,8 +137,10 @@ kV8CacheOptionsDefault), WorkerBackingThreadStartupData( WorkerBackingThreadStartupData::HeapLimitMode::kDefault, - WorkerBackingThreadStartupData::AtomicsWaitMode::kAllow), - script_url, v8_inspector::V8StackTraceId(), source); + WorkerBackingThreadStartupData::AtomicsWaitMode::kAllow)); + GetWorkerThread()->EvaluateClassicScript(script_url, source, + nullptr /* cached_meta_data */, + v8_inspector::V8StackTraceId()); } DedicatedWorkerThreadForTest* GetDedicatedWorkerThread() {
diff --git a/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.cpp b/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.cpp index 85252dd..a6ed380 100644 --- a/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.cpp +++ b/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.cpp
@@ -74,21 +74,17 @@ void ThreadedMessagingProxyBase::InitializeWorkerThread( std::unique_ptr<GlobalScopeCreationParams> global_scope_creation_params, - const WTF::Optional<WorkerBackingThreadStartupData>& thread_startup_data, - const KURL& script_url, - const v8_inspector::V8StackTraceId& stack_id, - const String& source_code) { + const WTF::Optional<WorkerBackingThreadStartupData>& thread_startup_data) { DCHECK(IsParentContextThread()); Document* document = ToDocument(GetExecutionContext()); + KURL script_url = global_scope_creation_params->script_url.Copy(); worker_thread_ = CreateWorkerThread(); worker_thread_->Start( std::move(global_scope_creation_params), thread_startup_data, - std::make_unique<GlobalScopeInspectorCreationParams>( - GetWorkerInspectorProxy()->ShouldPauseOnWorkerStart(document), - stack_id), - GetParentFrameTaskRunners(), source_code); + GetWorkerInspectorProxy()->ShouldPauseOnWorkerStart(document), + GetParentFrameTaskRunners()); GetWorkerInspectorProxy()->WorkerThreadCreated(document, GetWorkerThread(), script_url); }
diff --git a/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.h b/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.h index c879f64..68526c2 100644 --- a/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.h +++ b/third_party/WebKit/Source/core/workers/ThreadedMessagingProxyBase.h
@@ -16,10 +16,6 @@ #include "platform/wtf/Forward.h" #include "platform/wtf/Optional.h" -namespace v8_inspector { -struct V8StackTraceId; -} // namespace v8_inspector - namespace blink { class ExecutionContext; @@ -74,10 +70,7 @@ void InitializeWorkerThread( std::unique_ptr<GlobalScopeCreationParams>, - const WTF::Optional<WorkerBackingThreadStartupData>&, - const KURL& script_url, - const v8_inspector::V8StackTraceId&, - const String& source_code = String()); + const WTF::Optional<WorkerBackingThreadStartupData>&); ThreadableLoadingContext* CreateThreadableLoadingContext() const;
diff --git a/third_party/WebKit/Source/core/workers/ThreadedWorkletMessagingProxy.cpp b/third_party/WebKit/Source/core/workers/ThreadedWorkletMessagingProxy.cpp index 51254bb..8fb59e7c 100644 --- a/third_party/WebKit/Source/core/workers/ThreadedWorkletMessagingProxy.cpp +++ b/third_party/WebKit/Source/core/workers/ThreadedWorkletMessagingProxy.cpp
@@ -49,8 +49,7 @@ // Worklets share the pre-initialized backing thread so that we don't have to // specify the backing thread startup data. - InitializeWorkerThread(std::move(global_scope_creation_params), WTF::nullopt, - document->Url(), v8_inspector::V8StackTraceId()); + InitializeWorkerThread(std::move(global_scope_creation_params), WTF::nullopt); } void ThreadedWorkletMessagingProxy::Trace(blink::Visitor* visitor) {
diff --git a/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp b/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp index 60e5902f..2b43ed64 100644 --- a/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp +++ b/third_party/WebKit/Source/core/workers/ThreadedWorkletTest.cpp
@@ -181,7 +181,7 @@ worker_clients, document->AddressSpace(), OriginTrialContext::GetTokens(document).get(), std::move(worker_settings), kV8CacheOptionsDefault), - WTF::nullopt, document->Url(), v8_inspector::V8StackTraceId()); + WTF::nullopt); } private:
diff --git a/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.cpp b/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.cpp index c6f4564..564d9d9 100644 --- a/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.cpp
@@ -179,13 +179,4 @@ visitor->Trace(execution_context_); } -GlobalScopeInspectorCreationParams::GlobalScopeInspectorCreationParams( - WorkerInspectorProxy::PauseOnWorkerStart pause_on_start, - const v8_inspector::V8StackTraceId& stack_id) - : pause_on_start(pause_on_start), stack_id(stack_id) {} - -GlobalScopeInspectorCreationParams::GlobalScopeInspectorCreationParams( - WorkerInspectorProxy::PauseOnWorkerStart pause_on_start) - : pause_on_start(pause_on_start) {} - } // namespace blink
diff --git a/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.h b/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.h index 59906fd..2d0c0fbf 100644 --- a/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.h +++ b/third_party/WebKit/Source/core/workers/WorkerInspectorProxy.h
@@ -75,24 +75,6 @@ String inspector_id_; }; -struct CORE_EXPORT GlobalScopeInspectorCreationParams final { - USING_FAST_MALLOC(GlobalScopeInspectorCreationParams); - - public: - explicit GlobalScopeInspectorCreationParams( - WorkerInspectorProxy::PauseOnWorkerStart pause_on_start); - GlobalScopeInspectorCreationParams( - WorkerInspectorProxy::PauseOnWorkerStart pause_on_start, - const v8_inspector::V8StackTraceId&); - ~GlobalScopeInspectorCreationParams() = default; - - WorkerInspectorProxy::PauseOnWorkerStart pause_on_start; - v8_inspector::V8StackTraceId stack_id; - - private: - DISALLOW_COPY_AND_ASSIGN(GlobalScopeInspectorCreationParams); -}; - } // namespace blink #endif // WorkerInspectorProxy_h
diff --git a/third_party/WebKit/Source/core/workers/WorkerOrWorkletGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkerOrWorkletGlobalScope.cpp index e27192a6..070aad70 100644 --- a/third_party/WebKit/Source/core/workers/WorkerOrWorkletGlobalScope.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerOrWorkletGlobalScope.cpp
@@ -10,6 +10,7 @@ #include "core/frame/Deprecation.h" #include "core/inspector/ConsoleMessage.h" #include "core/loader/WorkerFetchContext.h" +#include "core/loader/modulescript/ModuleScriptFetchRequest.h" #include "core/probe/CoreProbes.h" #include "core/workers/MainThreadWorkletGlobalScope.h" #include "core/workers/WorkerReportingProxy.h" @@ -195,6 +196,28 @@ GetContentSecurityPolicy()->BindToExecutionContext(GetExecutionContext()); } +void WorkerOrWorkletGlobalScope::FetchModuleScript( + const KURL& module_url_record, + network::mojom::FetchCredentialsMode credentials_mode, + ModuleTreeClient* client) { + // Step 2: "Let options be a script fetch options whose cryptographic nonce is + // the empty string, + String nonce; + // integrity metadata is the empty string, + String integrity_attribute; + // parser metadata is "not-parser-inserted", + ParserDisposition parser_state = kNotParserInserted; + // and credentials mode is credentials mode." + ScriptFetchOptions options(nonce, IntegrityMetadataSet(), integrity_attribute, + parser_state, credentials_mode); + + Modulator* modulator = Modulator::From(ScriptController()->GetScriptState()); + // Step 3. "Perform the internal module script graph fetching procedure ..." + ModuleScriptFetchRequest module_request( + module_url_record, modulator->GetReferrerPolicy(), options); + modulator->FetchTree(module_request, client); +} + void WorkerOrWorkletGlobalScope::Trace(blink::Visitor* visitor) { visitor->Trace(resource_fetcher_); visitor->Trace(script_controller_);
diff --git a/third_party/WebKit/Source/core/workers/WorkerOrWorkletGlobalScope.h b/third_party/WebKit/Source/core/workers/WorkerOrWorkletGlobalScope.h index 1ec3e65..2581ab9 100644 --- a/third_party/WebKit/Source/core/workers/WorkerOrWorkletGlobalScope.h +++ b/third_party/WebKit/Source/core/workers/WorkerOrWorkletGlobalScope.h
@@ -14,10 +14,12 @@ #include "core/workers/WorkerClients.h" #include "core/workers/WorkerEventQueue.h" #include "platform/wtf/BitVector.h" +#include "services/network/public/interfaces/fetch_api.mojom-shared.h" namespace blink { class Modulator; +class ModuleTreeClient; class ResourceFetcher; class V8AbstractEventListener; class WorkerOrWorkletScriptController; @@ -112,6 +114,13 @@ void ApplyContentSecurityPolicyFromVector( const Vector<CSPHeaderAndType>& headers); + // Implementation of the "fetch a module worker script graph" algorithm in the + // HTML spec: + // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-module-worker-script-tree + void FetchModuleScript(const KURL& module_url_record, + network::mojom::FetchCredentialsMode, + ModuleTreeClient*); + private: CrossThreadPersistent<WorkerClients> worker_clients_; Member<ResourceFetcher> resource_fetcher_;
diff --git a/third_party/WebKit/Source/core/workers/WorkerThread.cpp b/third_party/WebKit/Source/core/workers/WorkerThread.cpp index eee284d..ea2cd37 100644 --- a/third_party/WebKit/Source/core/workers/WorkerThread.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerThread.cpp
@@ -98,11 +98,8 @@ void WorkerThread::Start( std::unique_ptr<GlobalScopeCreationParams> global_scope_creation_params, const WTF::Optional<WorkerBackingThreadStartupData>& thread_startup_data, - std::unique_ptr<GlobalScopeInspectorCreationParams> - global_scope_inspector_creation_params, - ParentFrameTaskRunners* parent_frame_task_runners, - const String& source_code, - std::unique_ptr<Vector<char>> cached_meta_data) { + WorkerInspectorProxy::PauseOnWorkerStart pause_on_start, + ParentFrameTaskRunners* parent_frame_task_runners) { DCHECK(IsMainThread()); DCHECK(!parent_frame_task_runners_); parent_frame_task_runners_ = parent_frame_task_runners; @@ -119,12 +116,23 @@ GetWorkerBackingThread().BackingThread().PostTask( BLINK_FROM_HERE, - CrossThreadBind( - &WorkerThread::InitializeOnWorkerThread, CrossThreadUnretained(this), - WTF::Passed(std::move(global_scope_creation_params)), - thread_startup_data, - WTF::Passed(std::move(global_scope_inspector_creation_params)), - source_code, WTF::Passed(std::move(cached_meta_data)))); + CrossThreadBind(&WorkerThread::InitializeOnWorkerThread, + CrossThreadUnretained(this), + WTF::Passed(std::move(global_scope_creation_params)), + thread_startup_data, pause_on_start)); +} + +void WorkerThread::EvaluateClassicScript( + const KURL& script_url, + const String& source_code, + std::unique_ptr<Vector<char>> cached_meta_data, + const v8_inspector::V8StackTraceId& stack_id) { + GetTaskRunner(TaskType::kUnthrottled) + ->PostTask( + BLINK_FROM_HERE, + CrossThreadBind(&WorkerThread::EvaluateClassicScriptOnWorkerThread, + CrossThreadUnretained(this), script_url, source_code, + WTF::Passed(std::move(cached_meta_data)), stack_id)); } void WorkerThread::Terminate() { @@ -386,10 +394,7 @@ void WorkerThread::InitializeOnWorkerThread( std::unique_ptr<GlobalScopeCreationParams> global_scope_creation_params, const WTF::Optional<WorkerBackingThreadStartupData>& thread_startup_data, - std::unique_ptr<GlobalScopeInspectorCreationParams> - global_scope_inspector_creation_params, - String source_code, - std::unique_ptr<Vector<char>> cached_meta_data) { + WorkerInspectorProxy::PauseOnWorkerStart pause_on_start) { DCHECK(IsCurrentThread()); DCHECK_EQ(ThreadState::kNotStarted, thread_state_); @@ -425,10 +430,8 @@ SetThreadState(lock, ThreadState::kRunning); } - if (global_scope_inspector_creation_params->pause_on_start == - WorkerInspectorProxy::PauseOnWorkerStart::kPause) { + if (pause_on_start == WorkerInspectorProxy::PauseOnWorkerStart::kPause) StartRunningDebuggerTasksOnPauseOnWorkerThread(); - } if (CheckRequestedToTerminateOnWorkerThread()) { // Stop further worker tasks from running after this point. WorkerThread @@ -437,19 +440,19 @@ PrepareForShutdownOnWorkerThread(); return; } +} - // Worklet will evaluate the script later via Worklet.addModule(). - // TODO(nhiroki): Start module loading for workers here. - // (https://crbug.com/680046) - if (GlobalScope()->IsWorkletGlobalScope()) - return; +void WorkerThread::EvaluateClassicScriptOnWorkerThread( + const KURL& script_url, + String source_code, + std::unique_ptr<Vector<char>> cached_meta_data, + const v8_inspector::V8StackTraceId& stack_id) { + DCHECK(GlobalScope()->IsWorkerGlobalScope()); WorkerThreadDebugger* debugger = WorkerThreadDebugger::From(GetIsolate()); - debugger->ExternalAsyncTaskStarted( - global_scope_inspector_creation_params->stack_id); + debugger->ExternalAsyncTaskStarted(stack_id); GlobalScope()->EvaluateClassicScript(script_url, std::move(source_code), std::move(cached_meta_data)); - debugger->ExternalAsyncTaskFinished( - global_scope_inspector_creation_params->stack_id); + debugger->ExternalAsyncTaskFinished(stack_id); } void WorkerThread::PrepareForShutdownOnWorkerThread() {
diff --git a/third_party/WebKit/Source/core/workers/WorkerThread.h b/third_party/WebKit/Source/core/workers/WorkerThread.h index d76e0bc..de8ad1b 100644 --- a/third_party/WebKit/Source/core/workers/WorkerThread.h +++ b/third_party/WebKit/Source/core/workers/WorkerThread.h
@@ -57,7 +57,6 @@ class WorkerOrWorkletGlobalScope; class WorkerReportingProxy; struct GlobalScopeCreationParams; -struct GlobalScopeInspectorCreationParams; // WorkerThread is a kind of WorkerBackingThread client. Each worker mechanism // can access the lower thread infrastructure via an implementation of this @@ -89,19 +88,25 @@ // Starts the underlying thread and creates the global scope. Called on the // main thread. // Startup data for WorkerBackingThread is WTF::nullopt if |this| doesn't own - // the underlying WorkerBackingThread. |source_code| is empty for module - // scripts or installed scripts. |cached_meta_data| is nullptr if the global - // scope to be created doesn't use V8 code caching. + // the underlying WorkerBackingThread. // TODO(nhiroki): We could separate WorkerBackingThread initialization from // GlobalScope initialization sequence, that is, InitializeOnWorkerThread(). // After that, we could remove this startup data for WorkerBackingThread. // (https://crbug.com/710364) void Start(std::unique_ptr<GlobalScopeCreationParams>, const WTF::Optional<WorkerBackingThreadStartupData>&, - std::unique_ptr<GlobalScopeInspectorCreationParams>, - ParentFrameTaskRunners*, - const String& source_code = String(), - std::unique_ptr<Vector<char>> cached_meta_data = nullptr); + WorkerInspectorProxy::PauseOnWorkerStart, + ParentFrameTaskRunners*); + + // Posts a task to evaluate a top-level classic script on the worker thread. + // Called on the main thread after Start(). + void EvaluateClassicScript(const KURL& script_url, + const String& source_code, + std::unique_ptr<Vector<char>> cached_meta_data, + const v8_inspector::V8StackTraceId& stack_id); + + // TODO(nhiroki): Implement ImportModuleScript() for module workers. + // (https://crbug.com/680046) // Closes the global scope and terminates the underlying thread. Called on the // main thread. @@ -241,9 +246,13 @@ void InitializeOnWorkerThread( std::unique_ptr<GlobalScopeCreationParams>, const WTF::Optional<WorkerBackingThreadStartupData>&, - std::unique_ptr<GlobalScopeInspectorCreationParams>, + WorkerInspectorProxy::PauseOnWorkerStart); + + void EvaluateClassicScriptOnWorkerThread( + const KURL& script_url, String source_code, - std::unique_ptr<Vector<char>> cached_meta_data); + std::unique_ptr<Vector<char>> cached_meta_data, + const v8_inspector::V8StackTraceId& stack_id); // These are called in this order during worker thread termination. void PrepareForShutdownOnWorkerThread();
diff --git a/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp b/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp index 3e4b95f3..e68986095 100644 --- a/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp +++ b/third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp
@@ -309,8 +309,7 @@ // on initialization to run debugger tasks. worker_thread_->Start(std::move(global_scope_creation_params), WorkerBackingThreadStartupData::CreateDefault(), - std::make_unique<GlobalScopeInspectorCreationParams>( - WorkerInspectorProxy::PauseOnWorkerStart::kPause), + WorkerInspectorProxy::PauseOnWorkerStart::kPause, ParentFrameTaskRunners::Create()); // Used to wait for worker thread termination in a debugger task on the
diff --git a/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h b/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h index 2c3a1e9..ae6b23b 100644 --- a/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h +++ b/third_party/WebKit/Source/core/workers/WorkerThreadTestHelper.h
@@ -108,9 +108,10 @@ Start(std::move(creation_params), WorkerBackingThreadStartupData::CreateDefault(), - std::make_unique<GlobalScopeInspectorCreationParams>( - WorkerInspectorProxy::PauseOnWorkerStart::kDontPause), - parent_frame_task_runners, source); + WorkerInspectorProxy::PauseOnWorkerStart::kDontPause, + parent_frame_task_runners); + EvaluateClassicScript(script_url, source, nullptr /* cached_meta_data */, + v8_inspector::V8StackTraceId()); } void WaitForInit() {
diff --git a/third_party/WebKit/Source/core/workers/WorkletGlobalScope.cpp b/third_party/WebKit/Source/core/workers/WorkletGlobalScope.cpp index 5f7e0e8bd..02f10b4 100644 --- a/third_party/WebKit/Source/core/workers/WorkletGlobalScope.cpp +++ b/third_party/WebKit/Source/core/workers/WorkletGlobalScope.cpp
@@ -10,7 +10,6 @@ #include "bindings/core/v8/WorkerOrWorkletScriptController.h" #include "core/dom/Modulator.h" #include "core/inspector/MainThreadDebugger.h" -#include "core/loader/modulescript/ModuleScriptFetchRequest.h" #include "core/probe/CoreProbes.h" #include "core/workers/GlobalScopeCreationParams.h" #include "core/workers/WorkerReportingProxy.h" @@ -100,30 +99,14 @@ // moduleURLRecord, moduleResponsesMap, credentialOptions, outsideSettings, // and insideSettings when it asynchronously completes." - // [FMWST] - // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-module-worker-script-tree - // [FMWST] Step 2: "Let options be a script fetch options whose cryptographic - // nonce is the empty string, - String nonce; - // integrity metadata is the empty string, - String integrity_attribute; - // parser metadata is "not-parser-inserted", - ParserDisposition parser_state = kNotParserInserted; - // and credentials mode is credentials mode. - ScriptFetchOptions options(nonce, IntegrityMetadataSet(), integrity_attribute, - parser_state, credentials_mode); - Modulator* modulator = Modulator::From(ScriptController()->GetScriptState()); - // [FMWST] Step 3. "Perform the internal module script graph fetching - // procedure ..." - ModuleScriptFetchRequest module_request( - module_url_record, modulator->GetReferrerPolicy(), options); // Step 3 to 5 are implemented in // WorkletModuleTreeClient::NotifyModuleTreeLoadFinished. WorkletModuleTreeClient* client = new WorkletModuleTreeClient( modulator, std::move(outside_settings_task_runner), pending_tasks); - modulator->FetchTree(module_request, client); + + FetchModuleScript(module_url_record, credentials_mode, client); } WorkletModuleResponsesMapProxy* WorkletGlobalScope::ModuleResponsesMapProxy()
diff --git a/third_party/WebKit/Source/devtools/front_end/application_test_runner/ResourcesTestRunner.js b/third_party/WebKit/Source/devtools/front_end/application_test_runner/ResourcesTestRunner.js index 26d6838..5fa29b90 100644 --- a/third_party/WebKit/Source/devtools/front_end/application_test_runner/ResourcesTestRunner.js +++ b/third_party/WebKit/Source/devtools/front_end/application_test_runner/ResourcesTestRunner.js
@@ -7,6 +7,17 @@ * @suppress {accessControls} */ +/** + * Many application panel tests are flaky because storage state (e.g. IndexedDB) + * doesn't get reset between tests. + */ +ApplicationTestRunner.resetState = async function() { + var securityOrigin = new Common.ParsedURL(TestRunner.url()).securityOrigin(); + var storageTypes = + ['appcache', 'cache_storage', 'cookies', 'indexeddb', 'local_storage', 'service_workers', 'websql']; + await TestRunner.mainTarget.storageAgent().clearDataForOrigin(securityOrigin, storageTypes.join(',')); +}; + ApplicationTestRunner.createWebSQLDatabase = function(name) { return TestRunner.evaluateInPageAsync(`_openWebSQLDatabase("${name}")`); };
diff --git a/third_party/WebKit/Source/devtools/front_end/text_editor/CodeMirrorTextEditor.js b/third_party/WebKit/Source/devtools/front_end/text_editor/CodeMirrorTextEditor.js index 8168e31..4e1ad31a 100644 --- a/third_party/WebKit/Source/devtools/front_end/text_editor/CodeMirrorTextEditor.js +++ b/third_party/WebKit/Source/devtools/front_end/text_editor/CodeMirrorTextEditor.js
@@ -141,8 +141,6 @@ this._codeMirror.setOption('keyMap', Host.isMac() ? 'devtools-mac' : 'devtools-pc'); - this._codeMirror.addKeyMap({'\'': 'maybeAvoidSmartSingleQuotes', '\'"\'': 'maybeAvoidSmartDoubleQuotes'}); - this._codeMirror.setOption('flattenSpans', false); var maxHighlightLength = options.maxHighlightLength; @@ -233,30 +231,6 @@ } /** - * @param {string} quoteCharacter - * @param {!CodeMirror} codeMirror - * @return {*} - */ - static _maybeAvoidSmartQuotes(quoteCharacter, codeMirror) { - var textEditor = codeMirror._codeMirrorTextEditor; - if (!codeMirror.getOption('autoCloseBrackets')) - return CodeMirror.Pass; - var selections = textEditor.selections(); - if (selections.length !== 1 || !selections[0].isEmpty()) - return CodeMirror.Pass; - - var selection = selections[0]; - var token = textEditor.tokenAtTextPosition(selection.startLine, selection.startColumn); - if (!token || !token.type || token.type.indexOf('string') === -1) - return CodeMirror.Pass; - var line = textEditor.line(selection.startLine); - var tokenValue = line.substring(token.startColumn, token.endColumn); - if (tokenValue[0] === tokenValue[tokenValue.length - 1] && (tokenValue[0] === '\'' || tokenValue[0] === '"')) - return CodeMirror.Pass; - codeMirror.replaceSelection(quoteCharacter); - } - - /** * @param {string} modeName * @param {string} tokenPrefix */ @@ -1401,12 +1375,6 @@ codemirror.execCommand('goPageDown'); }; - -CodeMirror.commands.maybeAvoidSmartSingleQuotes = - TextEditor.CodeMirrorTextEditor._maybeAvoidSmartQuotes.bind(null, '\''); -CodeMirror.commands.maybeAvoidSmartDoubleQuotes = - TextEditor.CodeMirrorTextEditor._maybeAvoidSmartQuotes.bind(null, '"'); - TextEditor.CodeMirrorTextEditor.LongLineModeLineLengthThreshold = 2000; TextEditor.CodeMirrorTextEditor.MaxEditableTextSize = 1024 * 1024 * 10;
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/XElement.js b/third_party/WebKit/Source/devtools/front_end/ui/XElement.js index 21bfd906..7c9ead9 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/XElement.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/XElement.js
@@ -45,3 +45,109 @@ } } }; + +/** + * @extends {UI.XElement} + */ +UI._XBox = class extends UI.XElement { + /** + * @param {string} direction + */ + constructor(direction) { + super(); + this.style.setProperty('display', 'flex'); + this.style.setProperty('flex-direction', direction); + this.style.setProperty('justify-content', 'flex-start'); + } + + static get observedAttributes() { + // TODO(dgozman): should be super.observedAttributes, but does not compile. + return UI.XElement.observedAttributes.concat(['x-start', 'x-center', 'x-stretch', 'x-baseline']); + } + + /** + * @param {string} attr + * @param {?string} oldValue + * @param {?string} newValue + * @override + */ + attributeChangedCallback(attr, oldValue, newValue) { + if (attr === 'x-start' || attr === 'x-center' || attr === 'x-stretch' || attr === 'x-baseline') { + if (newValue === null) + this.style.removeProperty('align-items'); + else + this.style.setProperty('align-items', attr === 'x-start' ? 'flex-start' : attr.substr(2)); + return; + } + super.attributeChangedCallback(attr, oldValue, newValue); + } +}; + +/** + * @extends {UI._XBox} + */ +UI.XVBox = class extends UI._XBox { + constructor() { + super('column'); + } +}; + +/** + * @extends {UI._XBox} + */ +UI.XHBox = class extends UI._XBox { + constructor() { + super('row'); + } +}; + +/** + * @extends {UI.XElement} + */ +UI.XCBox = class extends UI.XElement { + constructor() { + super(); + this.style.setProperty('display', 'flex'); + this.style.setProperty('flex-direction', 'column'); + this.style.setProperty('justify-content', 'center'); + this.style.setProperty('align-items', 'center'); + } +}; + +/** + * @extends {UI.XElement} + */ +UI.XDiv = class extends UI.XElement { + constructor() { + super(); + this.style.setProperty('display', 'block'); + } +}; + +/** + * @extends {UI.XElement} + */ +UI.XSpan = class extends UI.XElement { + constructor() { + super(); + this.style.setProperty('display', 'inline'); + } +}; + +/** + * @extends {UI.XElement} + */ +UI.XText = class extends UI.XElement { + constructor() { + super(); + this.style.setProperty('display', 'inline'); + this.style.setProperty('white-space', 'pre'); + } +}; + +self.customElements.define('x-vbox', UI.XVBox); +self.customElements.define('x-hbox', UI.XHBox); +self.customElements.define('x-cbox', UI.XCBox); +self.customElements.define('x-div', UI.XDiv); +self.customElements.define('x-span', UI.XSpan); +self.customElements.define('x-text', UI.XText);
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/inspectorSyntaxHighlight.css b/third_party/WebKit/Source/devtools/front_end/ui/inspectorSyntaxHighlight.css index f614bba3..c9c1678 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/inspectorSyntaxHighlight.css +++ b/third_party/WebKit/Source/devtools/front_end/ui/inspectorSyntaxHighlight.css
@@ -145,25 +145,25 @@ .cm-invalidchar {color: #f00;} -.cm-s-default .cm-header {color: blue;} -.cm-s-default .cm-quote {color: #090;} +.cm-header {color: blue;} +.cm-quote {color: #090;} -.cm-s-default .cm-keyword {color: #708;} -.cm-s-default .cm-atom {color: #219;} -.cm-s-default .cm-number {color: #164;} -.cm-s-default .cm-def {color: #00f;} -.cm-s-default .cm-variable-2 {color: #05a;} -.cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;} -.cm-s-default .cm-comment {color: #a50;} -.cm-s-default .cm-string {color: #a11;} -.cm-s-default .cm-string-2 {color: #f50;} -.cm-s-default .cm-meta {color: #555;} -.cm-s-default .cm-qualifier {color: #555;} -.cm-s-default .cm-builtin {color: #30a;} -.cm-s-default .cm-bracket {color: #997;} -.cm-s-default .cm-tag {color: #170;} -.cm-s-default .cm-attribute {color: #00c;} -.cm-s-default .cm-hr {color: #999;} -.cm-s-default .cm-link {color: #00c;} +.cm-keyword {color: #708;} +.cm-atom {color: #219;} +.cm-number {color: #164;} +.cm-def {color: #00f;} +.cm-variable-2 {color: #05a;} +.cm-variable-3, .cm-type {color: #085;} +.cm-comment {color: #a50;} +.cm-string {color: #a11;} +.cm-string-2 {color: #f50;} +.cm-meta {color: #555;} +.cm-qualifier {color: #555;} +.cm-builtin {color: #30a;} +.cm-bracket {color: #997;} +.cm-tag {color: #170;} +.cm-attribute {color: #00c;} +.cm-hr {color: #999;} +.cm-link {color: #00c;} -.cm-s-default .cm-error {color: #f00;} +.cm-error {color: #f00;}
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/inspectorSyntaxHighlightDark.css b/third_party/WebKit/Source/devtools/front_end/ui/inspectorSyntaxHighlightDark.css index 782ae591..ef50d41 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/inspectorSyntaxHighlightDark.css +++ b/third_party/WebKit/Source/devtools/front_end/ui/inspectorSyntaxHighlightDark.css
@@ -69,3 +69,20 @@ .webkit-css-property{color: rgb(53, 212, 199);} .webkit-css-string{color:rgb(231, 194, 111);} .webkit-css-url{color:rgb(231, 194, 111);} + +.cm-def{color:rgb(93, 176, 215);} +.cm-header{color:rgb(93, 176, 215);} +.cm-variable-2{color:rgb(217, 217, 217);} + +.cm-variable-2 {color: #05a;} +.cm-variable-3, .cm-type {color: rgb(93, 176, 215);} +.cm-string {color: rgb(242, 139, 84);} +.cm-meta {color: #555;} +.cm-meta {color:rgb(221, 251, 85);} +.cm-qualifier{color:rgb(255, 163, 79);} +.cm-builtin{color:rgb(159, 180, 214);} +.cm-bracket {color: #997;} +.cm-tag{color:rgb(93, 176, 215);} +.cm-attribute{color:rgb(97, 148, 198);} +.cm-hr {color: #999;} +.cm-link{color:rgb(159, 180, 214);}
diff --git a/third_party/WebKit/Source/modules/BUILD.gn b/third_party/WebKit/Source/modules/BUILD.gn index 19eb45f..a0b2844d 100644 --- a/third_party/WebKit/Source/modules/BUILD.gn +++ b/third_party/WebKit/Source/modules/BUILD.gn
@@ -324,6 +324,8 @@ "push_messaging/PushMessageDataTest.cpp", "remoteplayback/RemotePlaybackTest.cpp", "serviceworkers/ServiceWorkerContainerTest.cpp", + "serviceworkers/ServiceWorkerInstalledScriptsManagerTest.cpp", + "serviceworkers/ThreadSafeScriptContainerTest.cpp", "serviceworkers/WebEmbeddedWorkerImplTest.cpp", "wake_lock/ScreenWakeLockTest.cpp", "webaudio/AudioBasicProcessorHandlerTest.cpp",
diff --git a/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletGlobalScopeTest.cpp b/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletGlobalScopeTest.cpp index 23207f5a..c75b51c 100644 --- a/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletGlobalScopeTest.cpp +++ b/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletGlobalScopeTest.cpp
@@ -64,9 +64,7 @@ clients, document->AddressSpace(), OriginTrialContext::GetTokens(document).get(), nullptr /* worker_settings */, kV8CacheOptionsDefault), - WTF::nullopt, - std::make_unique<GlobalScopeInspectorCreationParams>( - WorkerInspectorProxy::PauseOnWorkerStart::kDontPause), + WTF::nullopt, WorkerInspectorProxy::PauseOnWorkerStart::kDontPause, ParentFrameTaskRunners::Create()); return thread; }
diff --git a/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletThreadTest.cpp b/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletThreadTest.cpp index 36bb05e..6ffda0a 100644 --- a/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletThreadTest.cpp +++ b/third_party/WebKit/Source/modules/animationworklet/AnimationWorkletThreadTest.cpp
@@ -98,9 +98,7 @@ clients, document->AddressSpace(), OriginTrialContext::GetTokens(document).get(), nullptr /* worker_settings */, kV8CacheOptionsDefault), - WTF::nullopt, - std::make_unique<GlobalScopeInspectorCreationParams>( - WorkerInspectorProxy::PauseOnWorkerStart::kDontPause), + WTF::nullopt, WorkerInspectorProxy::PauseOnWorkerStart::kDontPause, ParentFrameTaskRunners::Create()); return thread; }
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.cpp index ff3a2d4..a7b39cf 100644 --- a/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.cpp +++ b/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.cpp
@@ -28,7 +28,6 @@ #include "platform/graphics/CanvasHeuristicParameters.h" #include "platform/graphics/Color.h" #include "platform/graphics/Image.h" -#include "platform/graphics/ImageBuffer.h" #include "platform/graphics/StrokeData.h" #include "platform/graphics/paint/PaintCanvas.h" #include "platform/graphics/paint/PaintFlags.h" @@ -1130,7 +1129,7 @@ Optional<CustomCountHistogram> timer; if (!IsPaint2D()) { start_time = WTF::CurrentTimeTicksInSeconds(); - if (GetImageBuffer() && GetImageBuffer()->IsAccelerated()) { + if (CanCreateCanvas2DBuffer() && IsAccelerated()) { if (image_source->IsVideoElement()) { DEFINE_THREAD_SAFE_STATIC_LOCAL( CustomCountHistogram, scoped_us_counter_video_gpu, @@ -1201,10 +1200,9 @@ FloatSize default_object_size(Width(), Height()); SourceImageStatus source_image_status = kInvalidSourceImageStatus; if (!image_source->IsVideoElement()) { - AccelerationHint hint = - (HasImageBuffer() && GetImageBuffer()->IsAccelerated()) - ? kPreferAcceleration - : kPreferNoAcceleration; + AccelerationHint hint = (HasCanvas2DBuffer() && IsAccelerated()) + ? kPreferAcceleration + : kPreferNoAcceleration; image = image_source->GetSourceImageForCanvas(&source_image_status, hint, kSnapshotReasonDrawImage, default_object_size); @@ -1252,8 +1250,8 @@ // Heuristic for disabling acceleration based on anticipated texture upload // overhead. // See comments in CanvasHeuristicParameters.h for explanation. - ImageBuffer* buffer = GetImageBuffer(); - if (buffer && buffer->IsAccelerated() && !image_source->IsAccelerated()) { + if (CanCreateCanvas2DBuffer() && IsAccelerated() && + !image_source->IsAccelerated()) { float src_area = src_rect.Width() * src_rect.Height(); if (src_area > CanvasHeuristicParameters::kDrawImageTextureUploadHardSizeLimit) { @@ -1565,7 +1563,7 @@ Optional<ScopedUsHistogramTimer> timer; if (!IsPaint2D()) { - if (GetImageBuffer() && GetImageBuffer()->IsAccelerated()) { + if (CanCreateCanvas2DBuffer() && IsAccelerated()) { DEFINE_THREAD_SAFE_STATIC_LOCAL( CustomCountHistogram, scoped_us_counter_gpu, ("Blink.Canvas.GetImageData.GPU", 0, 10000000, 50)); @@ -1579,10 +1577,10 @@ } IntRect image_data_rect(sx, sy, sw, sh); - ImageBuffer* buffer = GetImageBuffer(); + bool hasImageBuffer = CanCreateCanvas2DBuffer(); ImageDataColorSettings color_settings = GetColorSettingsAsImageDataColorSettings(); - if (!buffer || isContextLost()) { + if (!hasImageBuffer || isContextLost()) { ImageData* result = ImageData::Create(image_data_rect.Size(), &color_settings); if (!result) @@ -1592,13 +1590,12 @@ WTF::ArrayBufferContents contents; - const CanvasColorParams& color_params = buffer->ColorParams(); - scoped_refptr<StaticBitmapImage> snapshot = buffer->NewImageSnapshot( - kPreferNoAcceleration, kSnapshotReasonGetImageData); + const CanvasColorParams& color_params = ColorParams(); + scoped_refptr<StaticBitmapImage> snapshot = + GetImage(kPreferNoAcceleration, kSnapshotReasonGetImageData); if (!StaticBitmapImage::ConvertToArrayBufferContents( - snapshot, contents, image_data_rect, color_params, - buffer->IsAccelerated())) { + snapshot, contents, image_data_rect, color_params, IsAccelerated())) { exception_state.ThrowRangeError("Out of memory at ImageData creation"); return nullptr; } @@ -1658,8 +1655,8 @@ return; } - ImageBuffer* buffer = GetImageBuffer(); - if (!buffer) + bool hasImageBuffer = CanCreateCanvas2DBuffer(); + if (!hasImageBuffer) return; if (dirty_width < 0) { @@ -1676,13 +1673,13 @@ dest_rect.Intersect(IntRect(0, 0, data->width(), data->height())); IntSize dest_offset(static_cast<int>(dx), static_cast<int>(dy)); dest_rect.Move(dest_offset); - dest_rect.Intersect(IntRect(IntPoint(), buffer->Size())); + dest_rect.Intersect(IntRect(0, 0, Width(), Height())); if (dest_rect.IsEmpty()) return; Optional<ScopedUsHistogramTimer> timer; if (!IsPaint2D()) { - if (GetImageBuffer() && GetImageBuffer()->IsAccelerated()) { + if (hasImageBuffer && IsAccelerated()) { DEFINE_THREAD_SAFE_STATIC_LOCAL( CustomCountHistogram, scoped_us_counter_gpu, ("Blink.Canvas.PutImageData.GPU", 0, 10000000, 50)); @@ -1708,27 +1705,81 @@ // is needed. CanvasColorParams data_color_params = data->GetCanvasColorParams(); CanvasColorParams context_color_params = - CanvasColorParams(ColorSpace(), PixelFormat(), kNonOpaque); + CanvasColorParams(ColorParams().ColorSpace(), PixelFormat(), kNonOpaque); if (data_color_params.NeedsColorConversion(context_color_params) || PixelFormat() == kF16CanvasPixelFormat) { unsigned data_length = data->Size().Area() * context_color_params.BytesPerPixel(); std::unique_ptr<uint8_t[]> converted_pixels(new uint8_t[data_length]); - if (data->ImageDataInCanvasColorSettings(ColorSpace(), PixelFormat(), - converted_pixels.get(), - kRGBAColorType)) { - buffer->PutByteArray(converted_pixels.get(), - IntSize(data->width(), data->height()), source_rect, - IntPoint(dest_offset)); + if (data->ImageDataInCanvasColorSettings( + ColorParams().ColorSpace(), PixelFormat(), converted_pixels.get(), + kRGBAColorType)) { + PutByteArray(converted_pixels.get(), + IntSize(data->width(), data->height()), source_rect, + IntPoint(dest_offset)); } } else { - buffer->PutByteArray(data->data()->Data(), - IntSize(data->width(), data->height()), source_rect, - IntPoint(dest_offset)); + PutByteArray(data->data()->Data(), IntSize(data->width(), data->height()), + source_rect, IntPoint(dest_offset)); } DidDraw(dest_rect); } +void BaseRenderingContext2D::PutByteArray(const unsigned char* source, + const IntSize& source_size, + const IntRect& source_rect, + const IntPoint& dest_point) { + if (!IsCanvas2DBufferValid()) + return; + uint8_t bytes_per_pixel = ColorParams().BytesPerPixel(); + + DCHECK_GT(source_rect.Width(), 0); + DCHECK_GT(source_rect.Height(), 0); + + int origin_x = source_rect.X(); + int dest_x = dest_point.X() + source_rect.X(); + DCHECK_GE(dest_x, 0); + DCHECK_LT(dest_x, Width()); + DCHECK_GE(origin_x, 0); + DCHECK_LT(origin_x, source_rect.MaxX()); + + int origin_y = source_rect.Y(); + int dest_y = dest_point.Y() + source_rect.Y(); + DCHECK_GE(dest_y, 0); + DCHECK_LT(dest_y, Height()); + DCHECK_GE(origin_y, 0); + DCHECK_LT(origin_y, source_rect.MaxY()); + + const size_t src_bytes_per_row = bytes_per_pixel * source_size.Width(); + const void* src_addr = + source + origin_y * src_bytes_per_row + origin_x * bytes_per_pixel; + + SkAlphaType alpha_type; + if (kOpaque == ColorParams().GetOpacityMode()) { + // If the surface is opaque, tell it that we are writing opaque + // pixels. Writing non-opaque pixels to opaque is undefined in + // Skia. There is some discussion about whether it should be + // defined in skbug.com/6157. For now, we can get the desired + // behavior (memcpy) by pretending the write is opaque. + alpha_type = kOpaque_SkAlphaType; + } else { + alpha_type = kUnpremul_SkAlphaType; + } + + SkImageInfo info; + if (ColorParams().GetSkColorSpaceForSkSurfaces()) { + info = SkImageInfo::Make(source_rect.Width(), source_rect.Height(), + ColorParams().GetSkColorType(), alpha_type, + ColorParams().GetSkColorSpaceForSkSurfaces()); + if (info.colorType() == kN32_SkColorType) + info = info.makeColorType(kRGBA_8888_SkColorType); + } else { + info = SkImageInfo::Make(source_rect.Width(), source_rect.Height(), + kRGBA_8888_SkColorType, alpha_type); + } + WritePixels(info, src_addr, src_bytes_per_row, dest_x, dest_y); +} + void BaseRenderingContext2D::InflateStrokeRect(FloatRect& rect) const { // Fast approximation of the stroke's bounding rect. // This yields a slightly oversized rect but is very fast @@ -1812,7 +1863,7 @@ image_type == CanvasRenderingContext2DState::kNoImage) { if (flags->HasShader()) { if (flags->ShaderIsOpaque() && alpha == 0xFF) - this->WillOverwriteCanvas(); + WillOverwriteCanvas(); return; } } @@ -1826,7 +1877,7 @@ return; } - this->WillOverwriteCanvas(); + WillOverwriteCanvas(); } float BaseRenderingContext2D::GetFontBaseline(
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.h b/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.h index e9a04ca..7030d01 100644 --- a/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.h +++ b/third_party/WebKit/Source/modules/canvas/canvas2d/BaseRenderingContext2D.h
@@ -15,6 +15,7 @@ #include "modules/canvas/canvas2d/CanvasStyle.h" #include "platform/graphics/CanvasHeuristicParameters.h" #include "platform/graphics/ColorBehavior.h" +#include "platform/graphics/StaticBitmapImage.h" #include "platform/graphics/paint/PaintCanvas.h" #include "third_party/skia/include/effects/SkComposeImageFilter.h" @@ -23,7 +24,6 @@ class CanvasImageSource; class Color; class Image; -class ImageBuffer; class Path2D; class SVGMatrixTearOff; @@ -224,10 +224,14 @@ virtual int Width() const = 0; virtual int Height() const = 0; - virtual bool HasImageBuffer() const { return false; } - virtual ImageBuffer* GetImageBuffer() const { + virtual bool IsAccelerated() const { NOTREACHED(); - return nullptr; + return false; + } + virtual bool HasCanvas2DBuffer() const { return false; } + virtual bool CanCreateCanvas2DBuffer() const { + NOTREACHED(); + return false; }; virtual bool ParseColorOrCurrentColor(Color&, @@ -251,7 +255,6 @@ virtual void WillDrawImage(CanvasImageSource*) const {} - virtual CanvasColorSpace ColorSpace() const { return kSRGBCanvasColorSpace; }; virtual String ColorSpaceAsString() const { return kSRGBCanvasColorSpaceName; } @@ -342,6 +345,21 @@ void UnwindStateStack(); + virtual CanvasColorParams ColorParams() const { return CanvasColorParams(); }; + virtual bool WritePixels(const SkImageInfo& orig_info, + const void* pixels, + size_t row_bytes, + int x, + int y) { + NOTREACHED(); + return false; + } + virtual scoped_refptr<StaticBitmapImage> GetImage(AccelerationHint, + SnapshotReason) const { + NOTREACHED(); + return nullptr; + } + enum DrawType { kClipFill, // Fill that is already known to cover the current clip kUntransformedUnclippedFill @@ -372,11 +390,7 @@ virtual void DidInvokeGPUReadbackInCurrentFrame() {} virtual bool IsPaint2D() const { return false; } - virtual void WillOverwriteCanvas() { - if (HasImageBuffer()) { - GetImageBuffer()->WillOverwriteCanvas(); - } - } + virtual void WillOverwriteCanvas() {} private: void RealizeSaves(); @@ -417,6 +431,15 @@ ImageDataColorSettings GetColorSettingsAsImageDataColorSettings() const; + void PutByteArray(const unsigned char* source, + const IntSize& source_size, + const IntRect& source_rect, + const IntPoint& dest_point); + virtual bool IsCanvas2DBufferValid() const { + NOTREACHED(); + return false; + } + bool origin_tainted_by_content_; };
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.cpp index 404d659..203a2b8 100644 --- a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.cpp +++ b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.cpp
@@ -38,7 +38,7 @@ #include "bindings/modules/v8/rendering_context.h" #include "core/CSSPropertyNames.h" #include "core/css/CSSFontSelector.h" -#include "core/css/MutableCSSPropertyValueSet.h" +#include "core/css/CSSPropertyValueSet.h" #include "core/css/StyleEngine.h" #include "core/css/resolver/StyleResolver.h" #include "core/dom/AXObjectCache.h" @@ -54,9 +54,9 @@ #include "modules/canvas/canvas2d/HitRegion.h" #include "modules/canvas/canvas2d/Path2D.h" #include "platform/fonts/FontCache.h" +#include "platform/graphics/Canvas2DLayerBridge.h" #include "platform/graphics/CanvasHeuristicParameters.h" #include "platform/graphics/DrawLooperBuilder.h" -#include "platform/graphics/ImageBuffer.h" #include "platform/graphics/StaticBitmapImage.h" #include "platform/graphics/StrokeData.h" #include "platform/graphics/paint/PaintCanvas.h" @@ -160,9 +160,10 @@ } bool CanvasRenderingContext2D::IsAccelerated() const { - if (!HasImageBuffer()) + Canvas2DLayerBridge* buffer2d = canvas()->Canvas2DBuffer(); + if (!buffer2d) return false; - return GetImageBuffer()->IsAccelerated(); + return buffer2d->IsAccelerated(); } bool CanvasRenderingContext2D::IsComposited() const { @@ -195,9 +196,9 @@ return; // This code path is for restoring from an eviction // Restoring from surface failure is handled internally - DCHECK(context_lost_mode_ != kNotLostContext && !HasImageBuffer()); + DCHECK(context_lost_mode_ != kNotLostContext && !HasCanvas2DBuffer()); - if (GetImageBuffer()) { + if (CanCreateCanvas2DBuffer()) { if (ContextLostRestoredEventsEnabled()) { dispatch_context_restored_event_timer_.StartOneShot(TimeDelta(), BLINK_FROM_HERE); @@ -244,7 +245,7 @@ } DCHECK(context_lost_mode_ == kRealLostContext); - if (HasImageBuffer() && GetImageBuffer()->RestoreSurface()) { + if (HasCanvas2DBuffer() && canvas()->Canvas2DBuffer()->Restore()) { try_restore_context_event_timer_.Stop(); DispatchContextRestoredEvent(nullptr); } @@ -253,7 +254,7 @@ // final attempt: allocate a brand new image buffer instead of restoring Host()->DiscardImageBuffer(); try_restore_context_event_timer_.Stop(); - if (GetImageBuffer()) + if (CanCreateCanvas2DBuffer()) DispatchContextRestoredEvent(nullptr); } } @@ -273,14 +274,29 @@ canvas()->WillDrawImageTo2DContext(source); } -CanvasColorSpace CanvasRenderingContext2D::ColorSpace() const { - return ColorParams().ColorSpace(); -} - String CanvasRenderingContext2D::ColorSpaceAsString() const { return CanvasRenderingContext::ColorSpaceAsString(); } +CanvasColorParams CanvasRenderingContext2D::ColorParams() const { + return CanvasRenderingContext::ColorParams(); +} + +bool CanvasRenderingContext2D::WritePixels(const SkImageInfo& orig_info, + const void* pixels, + size_t row_bytes, + int x, + int y) { + DCHECK(HasCanvas2DBuffer()); + return canvas()->Canvas2DBuffer()->WritePixels(orig_info, pixels, row_bytes, + x, y); +} + +void CanvasRenderingContext2D::WillOverwriteCanvas() { + if (HasCanvas2DBuffer()) + canvas()->Canvas2DBuffer()->WillOverwriteCanvas(); +} + CanvasPixelFormat CanvasRenderingContext2D::PixelFormat() const { return ColorParams().PixelFormat(); } @@ -602,21 +618,20 @@ return Host()->Size().Height(); } -bool CanvasRenderingContext2D::HasImageBuffer() const { - return Host()->GetImageBuffer(); +bool CanvasRenderingContext2D::HasCanvas2DBuffer() const { + return !!canvas()->Canvas2DBuffer(); } -ImageBuffer* CanvasRenderingContext2D::GetImageBuffer() const { - return const_cast<CanvasRenderingContextHost*>(Host()) - ->GetOrCreateImageBuffer(); +bool CanvasRenderingContext2D::CanCreateCanvas2DBuffer() const { + return canvas()->TryCreateImageBuffer(); } scoped_refptr<StaticBitmapImage> blink::CanvasRenderingContext2D::GetImage( AccelerationHint hint, SnapshotReason reason) const { - if (!HasImageBuffer()) + if (!HasCanvas2DBuffer()) return nullptr; - return GetImageBuffer()->NewImageSnapshot(hint, reason); + return canvas()->Canvas2DBuffer()->NewImageSnapshot(hint, reason); } bool CanvasRenderingContext2D::ParseColorOrCurrentColor( @@ -878,8 +893,8 @@ } void CanvasRenderingContext2D::SetIsHidden(bool hidden) { - if (HasImageBuffer()) - GetImageBuffer()->SetIsHidden(hidden); + if (HasCanvas2DBuffer()) + canvas()->Canvas2DBuffer()->SetIsHidden(hidden); if (hidden) { PruneLocalFontCache(0); } @@ -890,7 +905,7 @@ } WebLayer* CanvasRenderingContext2D::PlatformLayer() const { - return GetImageBuffer() ? GetImageBuffer()->PlatformLayer() : nullptr; + return HasCanvas2DBuffer() ? canvas()->Canvas2DBuffer()->Layer() : nullptr; } void CanvasRenderingContext2D::getContextAttributes( @@ -1069,4 +1084,11 @@ canvas()->DidInvokeGPUReadbackInCurrentFrame(); } +bool CanvasRenderingContext2D::IsCanvas2DBufferValid() const { + if (canvas()->Canvas2DBuffer()) { + return canvas()->Canvas2DBuffer()->IsValid(); + } + return false; +} + } // namespace blink
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.h b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.h index a72cd92..3f2bf104 100644 --- a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.h +++ b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2D.h
@@ -171,8 +171,8 @@ int Width() const final; int Height() const final; - bool HasImageBuffer() const final; - ImageBuffer* GetImageBuffer() const final; + bool HasCanvas2DBuffer() const final; + bool CanCreateCanvas2DBuffer() const final; bool ParseColorOrCurrentColor(Color&, const String& color_string) const final; @@ -180,9 +180,9 @@ PaintCanvas* ExistingDrawingCanvas() const final; void DisableDeferral(DisableDeferralReason) final; - void DidDraw(const SkIRect& dirty_rect) final; // overrides - // BaseRenderingContext2D and - // CanvasRenderingContext + void DidDraw(const SkIRect& dirty_rect) final; + scoped_refptr<StaticBitmapImage> GetImage(AccelerationHint, + SnapshotReason) const final; bool StateHasFilter() final; sk_sp<PaintFilter> StateGetFilter() final; @@ -190,12 +190,9 @@ void ValidateStateStack() const final; - scoped_refptr<StaticBitmapImage> GetImage(AccelerationHint, - SnapshotReason) const final; - void FinalizeFrame() override { usage_counters_.num_frames_since_reset++; } - bool IsPaintable() const final { return HasImageBuffer(); } + bool IsPaintable() const final { return HasCanvas2DBuffer(); } void WillDrawImage(CanvasImageSource*) const final; @@ -206,6 +203,14 @@ CanvasRenderingContext::NeedsFinalizeFrame(); } + CanvasColorParams ColorParams() const override; + bool WritePixels(const SkImageInfo& orig_info, + const void* pixels, + size_t row_bytes, + int x, + int y) override; + void WillOverwriteCanvas() override; + private: friend class CanvasRenderingContext2DAutoRestoreSkCanvas; @@ -236,7 +241,6 @@ return CanvasRenderingContext::kContext2d; } - CanvasColorSpace ColorSpace() const override; String ColorSpaceAsString() const override; CanvasPixelFormat PixelFormat() const override; @@ -250,6 +254,7 @@ virtual bool IsTransformInvertible() const; WebLayer* PlatformLayer() const override; + bool IsCanvas2DBufferValid() const override; Member<HitRegionManager> hit_region_manager_; LostContextMode context_lost_mode_;
diff --git a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DTest.cpp b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DTest.cpp index 968ee23..b54d2af9 100644 --- a/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DTest.cpp +++ b/third_party/WebKit/Source/modules/canvas/canvas2d/CanvasRenderingContext2DTest.cpp
@@ -25,7 +25,6 @@ #include "platform/graphics/CanvasHeuristicParameters.h" #include "platform/graphics/ColorCorrectionTestUtils.h" #include "platform/graphics/StaticBitmapImage.h" -#include "platform/graphics/UnacceleratedImageBufferSurface.h" #include "platform/graphics/gpu/SharedGpuContext.h" #include "platform/graphics/test/FakeGLES2Interface.h" #include "platform/graphics/test/FakeWebGraphicsContext3DProvider.h" @@ -261,14 +260,11 @@ //============================================================================ -class FakeAcceleratedImageBufferSurface - : public UnacceleratedImageBufferSurface { +class FakeAcceleratedImageBufferSurface : public Canvas2DLayerBridge { public: FakeAcceleratedImageBufferSurface(const IntSize& size, CanvasColorParams color_params) - : UnacceleratedImageBufferSurface(size, - kInitializeImagePixels, - color_params), + : Canvas2DLayerBridge(size, 0, kDisableAcceleration, color_params), is_accelerated_(true) {} ~FakeAcceleratedImageBufferSurface() override {} bool IsAccelerated() const override { return is_accelerated_; } @@ -639,7 +635,7 @@ MakeBridge(size, Canvas2DLayerBridge::kForceAccelerationForTesting); CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(bridge)); - EXPECT_TRUE(CanvasElement().GetImageBuffer()->IsAccelerated()); + EXPECT_TRUE(CanvasElement().Canvas2DBuffer()->IsAccelerated()); EXPECT_EQ(1u, GetGlobalAcceleratedContextCount()); EXPECT_EQ(720000, GetGlobalGPUMemoryUsage()); @@ -651,7 +647,7 @@ CanvasElement().FinalizeFrame(); EXPECT_FALSE(exception_state.HadException()); - EXPECT_TRUE(CanvasElement().GetImageBuffer()->IsAccelerated()); + EXPECT_TRUE(CanvasElement().Canvas2DBuffer()->IsAccelerated()); EXPECT_EQ(1u, GetGlobalAcceleratedContextCount()); EXPECT_EQ(720000, GetGlobalGPUMemoryUsage()); } @@ -661,11 +657,11 @@ EXPECT_FALSE(exception_state.HadException()); if (CanvasHeuristicParameters::kGPUReadbackForcesNoAcceleration) { - EXPECT_FALSE(CanvasElement().GetImageBuffer()->IsAccelerated()); + EXPECT_FALSE(CanvasElement().Canvas2DBuffer()->IsAccelerated()); EXPECT_EQ(0u, GetGlobalAcceleratedContextCount()); EXPECT_EQ(0, GetGlobalGPUMemoryUsage()); } else { - EXPECT_TRUE(CanvasElement().GetImageBuffer()->IsAccelerated()); + EXPECT_TRUE(CanvasElement().Canvas2DBuffer()->IsAccelerated()); EXPECT_EQ(1u, GetGlobalAcceleratedContextCount()); EXPECT_EQ(720000, GetGlobalGPUMemoryUsage()); } @@ -706,7 +702,7 @@ MakeBridge(size, Canvas2DLayerBridge::kEnableAcceleration); CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(bridge)); - EXPECT_TRUE(CanvasElement().GetImageBuffer()->IsAccelerated()); + EXPECT_TRUE(CanvasElement().Canvas2DBuffer()->IsAccelerated()); EXPECT_EQ(1u, GetGlobalAcceleratedContextCount()); // 4 bytes per pixel * 2 buffers = 8 EXPECT_EQ(8 * dst_size * dst_size, GetGlobalGPUMemoryUsage()); @@ -722,11 +718,11 @@ EXPECT_FALSE(exception_state.HadException()); if (test_variant == kLargeTextureDisablesAcceleration) { - EXPECT_FALSE(CanvasElement().GetImageBuffer()->IsAccelerated()); + EXPECT_FALSE(CanvasElement().Canvas2DBuffer()->IsAccelerated()); EXPECT_EQ(0u, GetGlobalAcceleratedContextCount()); EXPECT_EQ(0, GetGlobalGPUMemoryUsage()); } else { - EXPECT_TRUE(CanvasElement().GetImageBuffer()->IsAccelerated()); + EXPECT_TRUE(CanvasElement().Canvas2DBuffer()->IsAccelerated()); EXPECT_EQ(1u, GetGlobalAcceleratedContextCount()); EXPECT_EQ(8 * dst_size * dst_size, GetGlobalGPUMemoryUsage()); } @@ -750,10 +746,10 @@ EXPECT_EQ(1u, GetGlobalAcceleratedContextCount()); context->fillRect(10, 10, 100, 100); - EXPECT_TRUE(CanvasElement().GetImageBuffer()->IsAccelerated()); + EXPECT_TRUE(CanvasElement().Canvas2DBuffer()->IsAccelerated()); CanvasElement().DisableAcceleration(); - EXPECT_FALSE(CanvasElement().GetImageBuffer()->IsAccelerated()); + EXPECT_FALSE(CanvasElement().Canvas2DBuffer()->IsAccelerated()); context->fillRect(10, 10, 100, 100); @@ -1099,9 +1095,9 @@ bridge->DontUseIdleSchedulingForTesting(); CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(bridge)); - EXPECT_TRUE(CanvasElement().GetImageBuffer()->IsAccelerated()); + EXPECT_TRUE(CanvasElement().Canvas2DBuffer()->IsAccelerated()); // Take a snapshot to trigger lazy resource provider creation - CanvasElement().GetImageBuffer()->NewImageSnapshot(kPreferAcceleration, + CanvasElement().Canvas2DBuffer()->NewImageSnapshot(kPreferAcceleration, kSnapshotReasonUnknown); EXPECT_TRUE(CanvasElement().GetLayoutBoxModelObject()); PaintLayer* layer = CanvasElement().GetLayoutBoxModelObject()->Layer(); @@ -1137,7 +1133,7 @@ bridge->DontUseIdleSchedulingForTesting(); CanvasElement().CreateImageBufferUsingSurfaceForTesting(std::move(bridge)); - EXPECT_TRUE(CanvasElement().GetImageBuffer()->IsAccelerated()); + EXPECT_TRUE(CanvasElement().Canvas2DBuffer()->IsAccelerated()); EXPECT_TRUE(CanvasElement().GetLayoutBoxModelObject()); PaintLayer* layer = CanvasElement().GetLayoutBoxModelObject()->Layer();
diff --git a/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp index e68d37f9..e8a81c76 100644 --- a/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp +++ b/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.cpp
@@ -91,23 +91,25 @@ return Host()->Size().Height(); } -bool OffscreenCanvasRenderingContext2D::HasImageBuffer() const { - return Host()->GetImageBuffer(); +bool OffscreenCanvasRenderingContext2D::HasCanvas2DBuffer() const { + return !!offscreenCanvasForBinding()->GetImageBuffer(); } +bool OffscreenCanvasRenderingContext2D::CanCreateCanvas2DBuffer() const { + return !!offscreenCanvasForBinding()->GetOrCreateImageBuffer(); +} + +ImageBuffer* OffscreenCanvasRenderingContext2D::GetImageBuffer() const { + return offscreenCanvasForBinding()->GetImageBuffer(); +} void OffscreenCanvasRenderingContext2D::Reset() { Host()->DiscardImageBuffer(); BaseRenderingContext2D::Reset(); } -ImageBuffer* OffscreenCanvasRenderingContext2D::GetImageBuffer() const { - return const_cast<CanvasRenderingContextHost*>(Host()) - ->GetOrCreateImageBuffer(); -} - scoped_refptr<StaticBitmapImage> OffscreenCanvasRenderingContext2D::TransferToStaticBitmapImage() { - if (!GetImageBuffer()) + if (!CanCreateCanvas2DBuffer()) return nullptr; scoped_refptr<StaticBitmapImage> image = GetImageBuffer()->NewImageSnapshot( kPreferAcceleration, kSnapshotReasonTransferToImageBitmap); @@ -136,7 +138,7 @@ scoped_refptr<StaticBitmapImage> OffscreenCanvasRenderingContext2D::GetImage( AccelerationHint hint, SnapshotReason reason) const { - if (!GetImageBuffer()) + if (!CanCreateCanvas2DBuffer()) return nullptr; scoped_refptr<StaticBitmapImage> image = GetImageBuffer()->NewImageSnapshot(hint, reason); @@ -155,14 +157,13 @@ } PaintCanvas* OffscreenCanvasRenderingContext2D::DrawingCanvas() const { - ImageBuffer* buffer = GetImageBuffer(); - if (!buffer) + if (!CanCreateCanvas2DBuffer()) return nullptr; return GetImageBuffer()->Canvas(); } PaintCanvas* OffscreenCanvasRenderingContext2D::ExistingDrawingCanvas() const { - if (!HasImageBuffer()) + if (!HasCanvas2DBuffer()) return nullptr; return GetImageBuffer()->Canvas(); } @@ -196,11 +197,7 @@ } bool OffscreenCanvasRenderingContext2D::IsPaintable() const { - return GetImageBuffer(); -} - -CanvasColorSpace OffscreenCanvasRenderingContext2D::ColorSpace() const { - return ColorParams().ColorSpace(); + return CanCreateCanvas2DBuffer(); } String OffscreenCanvasRenderingContext2D::ColorSpaceAsString() const { @@ -211,8 +208,23 @@ return ColorParams().PixelFormat(); } +CanvasColorParams OffscreenCanvasRenderingContext2D::ColorParams() const { + return CanvasRenderingContext::ColorParams(); +} + +bool OffscreenCanvasRenderingContext2D::WritePixels( + const SkImageInfo& orig_info, + const void* pixels, + size_t row_bytes, + int x, + int y) { + DCHECK(HasCanvas2DBuffer()); + return offscreenCanvasForBinding()->GetImageBuffer()->WritePixels( + orig_info, pixels, row_bytes, x, y); +} + bool OffscreenCanvasRenderingContext2D::IsAccelerated() const { - return HasImageBuffer() && GetImageBuffer()->IsAccelerated(); + return HasCanvas2DBuffer() && GetImageBuffer()->IsAccelerated(); } String OffscreenCanvasRenderingContext2D::font() const { @@ -461,4 +473,10 @@ setFont(GetState().UnparsedFont()); return GetState().GetFont(); } + +bool OffscreenCanvasRenderingContext2D::IsCanvas2DBufferValid() const { + if (HasCanvas2DBuffer()) + return GetImageBuffer()->IsSurfaceValid(); + return false; +} } // namespace blink
diff --git a/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h b/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h index 8327ee61..715979c 100644 --- a/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h +++ b/third_party/WebKit/Source/modules/canvas/offscreencanvas2d/OffscreenCanvasRenderingContext2D.h
@@ -87,8 +87,9 @@ int Width() const final; int Height() const final; - bool HasImageBuffer() const final; - ImageBuffer* GetImageBuffer() const final; + bool HasCanvas2DBuffer() const final; + bool CanCreateCanvas2DBuffer() const final; + ImageBuffer* GetImageBuffer() const; bool ParseColorOrCurrentColor(Color&, const String& color_string) const final; @@ -122,8 +123,16 @@ CanvasRenderingContext::NeedsFinalizeFrame(); } + CanvasColorParams ColorParams() const override; + bool WritePixels(const SkImageInfo& orig_info, + const void* pixels, + size_t row_bytes, + int x, + int y) override; + private: bool IsPaintable() const final; + bool IsCanvas2DBufferValid() const override; void DrawTextInternal(const String&, double, @@ -134,7 +143,6 @@ scoped_refptr<StaticBitmapImage> TransferToStaticBitmapImage(); - CanvasColorSpace ColorSpace() const override; String ColorSpaceAsString() const override; CanvasPixelFormat PixelFormat() const override; SkIRect dirty_rect_for_commit_;
diff --git a/third_party/WebKit/Source/modules/cookie_store/CookieStore.cpp b/third_party/WebKit/Source/modules/cookie_store/CookieStore.cpp index efdafb3..3977205 100644 --- a/third_party/WebKit/Source/modules/cookie_store/CookieStore.cpp +++ b/third_party/WebKit/Source/modules/cookie_store/CookieStore.cpp
@@ -177,8 +177,13 @@ Document* document = ToDocument(execution_context); cookie_url = document->CookieURL(); site_for_cookies = document->SiteForCookies(); + } else if (execution_context->IsServiceWorkerGlobalScope()) { + ServiceWorkerGlobalScope* scope = + ToServiceWorkerGlobalScope(execution_context); + // TODO(crbug.com/729800): Correct values? + cookie_url = scope->Url(); + site_for_cookies = scope->Url(); } else { - // TODO(crbug.com/729800): Add branch for service workers. NOTIMPLEMENTED(); } } @@ -388,6 +393,10 @@ // static void CookieStore::OnSetCanonicalCookieResult(ScriptPromiseResolver* resolver, bool backend_success) { + ScriptState* script_state = resolver->GetScriptState(); + if (!script_state->ContextIsValid()) + return; + if (!backend_success) { resolver->Reject(DOMException::Create( kUnknownError, "An unknown error occured while writing the cookie."));
diff --git a/third_party/WebKit/Source/modules/cookie_store/CookieStore.idl b/third_party/WebKit/Source/modules/cookie_store/CookieStore.idl index a20c9e9..61c88826 100644 --- a/third_party/WebKit/Source/modules/cookie_store/CookieStore.idl +++ b/third_party/WebKit/Source/modules/cookie_store/CookieStore.idl
@@ -5,7 +5,7 @@ // https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md [ - Exposed=Window, + Exposed=(ServiceWorker,Window), RuntimeEnabled=AsyncCookies ] interface CookieStore { // https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md#reading
diff --git a/third_party/WebKit/Source/modules/cookie_store/GlobalCookieStore.cpp b/third_party/WebKit/Source/modules/cookie_store/GlobalCookieStore.cpp index fa1cd4a..76eda5fa5 100644 --- a/third_party/WebKit/Source/modules/cookie_store/GlobalCookieStore.cpp +++ b/third_party/WebKit/Source/modules/cookie_store/GlobalCookieStore.cpp
@@ -10,6 +10,7 @@ #include "core/frame/LocalFrame.h" #include "core/workers/WorkerThread.h" #include "modules/cookie_store/CookieStore.h" +#include "modules/serviceworkers/ServiceWorkerGlobalScope.h" #include "platform/Supplementable.h" #include "platform/heap/Handle.h" #include "services/network/public/interfaces/restricted_cookie_manager.mojom-blink.h" @@ -36,21 +37,10 @@ return *supplement; } - CookieStore* GetCookieStore(); - - virtual void Trace(blink::Visitor* visitor) { - visitor->Trace(cookie_store_); - Supplement<T>::Trace(visitor); - } - - private: - explicit GlobalCookieStoreImpl(T& supplementable) - : Supplement<T>(supplementable) {} - - static const char* GetName() { return "CookieStore"; } - - CookieStore* GetCookieStore(ExecutionContext* execution_context) { + CookieStore* GetCookieStore(T& scope) { if (!cookie_store_) { + ExecutionContext* execution_context = scope.GetExecutionContext(); + network::mojom::blink::RestrictedCookieManagerPtr cookie_manager_ptr; service_manager::InterfaceProvider* interface_provider = execution_context->GetInterfaceProvider(); @@ -63,21 +53,32 @@ return cookie_store_; } + virtual void Trace(blink::Visitor* visitor) { + visitor->Trace(cookie_store_); + Supplement<T>::Trace(visitor); + } + + private: + explicit GlobalCookieStoreImpl(T& supplementable) + : Supplement<T>(supplementable) {} + + static const char* GetName() { return "CookieStore"; } + Member<CookieStore> cookie_store_; }; -template <> -CookieStore* GlobalCookieStoreImpl<LocalDOMWindow>::GetCookieStore() { - LocalDOMWindow* window = GetSupplementable(); - return GetCookieStore(window->document()); -} - -// TODO(crbug.com/729800): Add ServiceWorkerGlobalScope overload. - } // namespace CookieStore* GlobalCookieStore::cookieStore(LocalDOMWindow& window) { - return GlobalCookieStoreImpl<LocalDOMWindow>::From(window).GetCookieStore(); + return GlobalCookieStoreImpl<LocalDOMWindow>::From(window).GetCookieStore( + window); +} + +CookieStore* GlobalCookieStore::cookieStore(ServiceWorkerGlobalScope& worker) { + // ServiceWorkerGlobalScope is Supplementable<WorkerGlobalScope>, not + // Supplementable<ServiceWorkerGlobalScope>. + return GlobalCookieStoreImpl<WorkerGlobalScope>::From(worker).GetCookieStore( + worker); } } // namespace blink
diff --git a/third_party/WebKit/Source/modules/cookie_store/GlobalCookieStore.h b/third_party/WebKit/Source/modules/cookie_store/GlobalCookieStore.h index 1537230..397bd58 100644 --- a/third_party/WebKit/Source/modules/cookie_store/GlobalCookieStore.h +++ b/third_party/WebKit/Source/modules/cookie_store/GlobalCookieStore.h
@@ -11,6 +11,7 @@ class CookieStore; class LocalDOMWindow; +class ServiceWorkerGlobalScope; // Exposes a CookieStore as the "cookieStore" attribute on the global scope. // @@ -20,8 +21,7 @@ public: static CookieStore* cookieStore(LocalDOMWindow&); - - // TODO(crbug.com/729800): Expose to ServiceWorkerGlobalScope. + static CookieStore* cookieStore(ServiceWorkerGlobalScope&); }; } // namespace blink
diff --git a/third_party/WebKit/Source/modules/cookie_store/ServiceWorkerGlobalScopeCookieStore.idl b/third_party/WebKit/Source/modules/cookie_store/ServiceWorkerGlobalScopeCookieStore.idl new file mode 100644 index 0000000..eebb8b7 --- /dev/null +++ b/third_party/WebKit/Source/modules/cookie_store/ServiceWorkerGlobalScopeCookieStore.idl
@@ -0,0 +1,12 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md + +[ + RuntimeEnabled=AsyncCookies, + ImplementedAs=GlobalCookieStore +] partial interface ServiceWorkerGlobalScope { + [Replaceable, SameObject] readonly attribute CookieStore cookieStore; +};
diff --git a/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.h b/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.h index 071c6cbd..55a98197 100644 --- a/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.h +++ b/third_party/WebKit/Source/modules/csspaint/PaintRenderingContext2D.h
@@ -10,6 +10,8 @@ #include "modules/canvas/canvas2d/BaseRenderingContext2D.h" #include "modules/csspaint/PaintRenderingContext2DSettings.h" #include "platform/bindings/ScriptWrappable.h" +#include "platform/graphics/paint/PaintRecord.h" +#include "platform/graphics/paint/PaintRecorder.h" namespace blink {
diff --git a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp index 4288c9a..65a51827 100644 --- a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp +++ b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.cpp
@@ -60,6 +60,7 @@ #include "platform/weborigin/SecurityOrigin.h" #include "platform/wtf/Functional.h" #include "platform/wtf/PtrUtil.h" +#include "public/platform/Platform.h" #include "public/platform/TaskType.h" #include "public/platform/WebURLRequest.h" #include "public/platform/WebWorkerFetchContext.h" @@ -69,17 +70,19 @@ #include "public/web/WebDevToolsAgent.h" #include "public/web/WebSettings.h" #include "public/web/modules/serviceworker/WebServiceWorkerContextClient.h" +#include "third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom-blink.h" namespace blink { +// static std::unique_ptr<WebEmbeddedWorker> WebEmbeddedWorker::Create( std::unique_ptr<WebServiceWorkerContextClient> client, - std::unique_ptr<WebServiceWorkerInstalledScriptsManager> - installed_scripts_manager, + std::unique_ptr<WebServiceWorkerInstalledScriptsManagerParams> + installed_scripts_manager_params, mojo::ScopedMessagePipeHandle content_settings_handle, mojo::ScopedMessagePipeHandle interface_provider) { return std::make_unique<WebEmbeddedWorkerImpl>( - std::move(client), std::move(installed_scripts_manager), + std::move(client), std::move(installed_scripts_manager_params), std::make_unique<ServiceWorkerContentSettingsProxy>( // Chrome doesn't use interface versioning. mojom::blink::WorkerContentSettingsProxyPtrInfo( @@ -89,10 +92,25 @@ service_manager::mojom::blink::InterfaceProvider::Version_)); } +// static +std::unique_ptr<WebEmbeddedWorkerImpl> WebEmbeddedWorkerImpl::CreateForTesting( + std::unique_ptr<WebServiceWorkerContextClient> client, + std::unique_ptr<ServiceWorkerInstalledScriptsManager> + installed_scripts_manager) { + auto worker_impl = std::make_unique<WebEmbeddedWorkerImpl>( + std::move(client), nullptr /* installed_scripts_manager_params */, + std::make_unique<ServiceWorkerContentSettingsProxy>( + nullptr /* host_info */), + nullptr /* interface_provider_info */); + worker_impl->installed_scripts_manager_ = + std::move(installed_scripts_manager); + return worker_impl; +} + WebEmbeddedWorkerImpl::WebEmbeddedWorkerImpl( std::unique_ptr<WebServiceWorkerContextClient> client, - std::unique_ptr<WebServiceWorkerInstalledScriptsManager> - installed_scripts_manager, + std::unique_ptr<WebServiceWorkerInstalledScriptsManagerParams> + installed_scripts_manager_params, std::unique_ptr<ServiceWorkerContentSettingsProxy> content_settings_client, service_manager::mojom::blink::InterfaceProviderPtrInfo interface_provider_info) @@ -103,10 +121,18 @@ waiting_for_debugger_state_(kNotWaitingForDebugger), interface_provider_info_(std::move(interface_provider_info)) { if (RuntimeEnabledFeatures::ServiceWorkerScriptStreamingEnabled() && - installed_scripts_manager) { - installed_scripts_manager_ = - std::make_unique<ServiceWorkerInstalledScriptsManager>( - std::move(installed_scripts_manager)); + installed_scripts_manager_params) { + DCHECK(installed_scripts_manager_params->manager_request.is_valid()); + DCHECK(installed_scripts_manager_params->manager_host_ptr.is_valid()); + installed_scripts_manager_ = std::make_unique< + ServiceWorkerInstalledScriptsManager>( + std::move(installed_scripts_manager_params->installed_scripts_urls), + mojom::blink::ServiceWorkerInstalledScriptsManagerRequest( + std::move(installed_scripts_manager_params->manager_request)), + mojom::blink::ServiceWorkerInstalledScriptsManagerHostPtrInfo( + std::move(installed_scripts_manager_params->manager_host_ptr), + mojom::blink::ServiceWorkerInstalledScriptsManagerHost::Version_), + Platform::Current()->GetIOTaskRunner()); } } @@ -431,13 +457,16 @@ worker_thread_->Start( std::move(global_scope_creation_params), WorkerBackingThreadStartupData::CreateDefault(), - std::make_unique<GlobalScopeInspectorCreationParams>( - worker_inspector_proxy_->ShouldPauseOnWorkerStart(document)), - ParentFrameTaskRunners::Create(), source_code, - std::move(cached_meta_data)); + worker_inspector_proxy_->ShouldPauseOnWorkerStart(document), + ParentFrameTaskRunners::Create()); worker_inspector_proxy_->WorkerThreadCreated(document, worker_thread_.get(), worker_start_data_.script_url); + + // TODO(nhiroki): Support module workers (https://crbug.com/680046). + worker_thread_->EvaluateClassicScript( + worker_start_data_.script_url, source_code, std::move(cached_meta_data), + v8_inspector::V8StackTraceId()); } } // namespace blink
diff --git a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.h b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.h index befbf04..e2930b2 100644 --- a/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.h +++ b/third_party/WebKit/Source/modules/exported/WebEmbeddedWorkerImpl.h
@@ -61,7 +61,7 @@ public: WebEmbeddedWorkerImpl( std::unique_ptr<WebServiceWorkerContextClient>, - std::unique_ptr<WebServiceWorkerInstalledScriptsManager>, + std::unique_ptr<WebServiceWorkerInstalledScriptsManagerParams>, std::unique_ptr<ServiceWorkerContentSettingsProxy>, service_manager::mojom::blink::InterfaceProviderPtrInfo); ~WebEmbeddedWorkerImpl() override; @@ -93,6 +93,10 @@ WebApplicationCacheHostClient*) override; void OnShadowPageInitialized() override; + static std::unique_ptr<WebEmbeddedWorkerImpl> CreateForTesting( + std::unique_ptr<WebServiceWorkerContextClient>, + std::unique_ptr<ServiceWorkerInstalledScriptsManager>); + private: // WebDevToolsAgentClient overrides. void SendProtocolMessage(int session_id,
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBRequestTest.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBRequestTest.cpp index 2aac369..4035032 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBRequestTest.cpp +++ b/third_party/WebKit/Source/modules/indexeddb/IDBRequestTest.cpp
@@ -108,13 +108,14 @@ request->HandleResponse( DOMException::Create(kAbortError, "Description goes here.")); request->HandleResponse(nullptr, IDBKey::CreateInvalid(), - IDBKey::CreateInvalid(), IDBValue::Create()); + IDBKey::CreateInvalid(), + CreateNullIDBValueForTesting()); request->HandleResponse(IDBKey::CreateInvalid()); - request->HandleResponse(IDBValue::Create()); + request->HandleResponse(CreateNullIDBValueForTesting()); request->HandleResponse(static_cast<int64_t>(0)); request->HandleResponse(); request->HandleResponse(IDBKey::CreateInvalid(), IDBKey::CreateInvalid(), - IDBValue::Create()); + CreateNullIDBValueForTesting()); request->EnqueueResponse(Vector<String>()); EXPECT_TRUE(!exception_state.HadException());
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBTestHelper.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBTestHelper.cpp index 4fd53cb..e3bb3ca1 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBTestHelper.cpp +++ b/third_party/WebKit/Source/modules/indexeddb/IDBTestHelper.cpp
@@ -17,6 +17,23 @@ namespace blink { +std::unique_ptr<IDBValue> CreateNullIDBValueForTesting() { + scoped_refptr<SerializedScriptValue> null_ssv = + SerializedScriptValue::NullValue(); + + StringView ssv_wire_bytes = null_ssv->GetWireData(); + DCHECK(ssv_wire_bytes.Is8Bit()); + + scoped_refptr<SharedBuffer> idb_value_buffer = SharedBuffer::Create(); + idb_value_buffer->Append( + reinterpret_cast<const char*>(ssv_wire_bytes.Characters8()), + ssv_wire_bytes.length()); + return IDBValue::Create(std::move(idb_value_buffer), + Vector<scoped_refptr<BlobDataHandle>>(), + Vector<WebBlobInfo>(), IDBKey::CreateNumber(42.0), + IDBKeyPath(String("primaryKey"))); +} + std::unique_ptr<IDBValue> CreateIDBValueForTesting(v8::Isolate* isolate, bool create_wrapped_value) { size_t element_count = create_wrapped_value ? 16 : 2;
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBTestHelper.h b/third_party/WebKit/Source/modules/indexeddb/IDBTestHelper.h index 1d70d44..ce8a6d6 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBTestHelper.h +++ b/third_party/WebKit/Source/modules/indexeddb/IDBTestHelper.h
@@ -11,6 +11,8 @@ namespace blink { +std::unique_ptr<IDBValue> CreateNullIDBValueForTesting(); + // The created value is an array of true. If create_wrapped_value is true, the // IDBValue's byte array will be wrapped in a Blob, otherwise it will not be. std::unique_ptr<IDBValue> CreateIDBValueForTesting(v8::Isolate*,
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBValue.cpp b/third_party/WebKit/Source/modules/indexeddb/IDBValue.cpp index 2d753364..67ee72bd 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBValue.cpp +++ b/third_party/WebKit/Source/modules/indexeddb/IDBValue.cpp
@@ -16,8 +16,6 @@ namespace blink { -IDBValue::IDBValue() = default; - IDBValue::IDBValue(const WebIDBValue& value, v8::Isolate* isolate) : IDBValue(value.data, value.web_blob_info, @@ -72,10 +70,6 @@ isolate_->AdjustAmountOfExternalAllocatedMemory(-external_allocated_size_); } -std::unique_ptr<IDBValue> IDBValue::Create() { - return WTF::WrapUnique(new IDBValue()); -} - std::unique_ptr<IDBValue> IDBValue::Create(const WebIDBValue& value, v8::Isolate* isolate) { return WTF::WrapUnique(new IDBValue(value, isolate));
diff --git a/third_party/WebKit/Source/modules/indexeddb/IDBValue.h b/third_party/WebKit/Source/modules/indexeddb/IDBValue.h index fa468c7..c8ba4c9 100644 --- a/third_party/WebKit/Source/modules/indexeddb/IDBValue.h +++ b/third_party/WebKit/Source/modules/indexeddb/IDBValue.h
@@ -24,7 +24,6 @@ class MODULES_EXPORT IDBValue final { public: - static std::unique_ptr<IDBValue> Create(); static std::unique_ptr<IDBValue> Create(const WebIDBValue&, v8::Isolate*); // Injects a primary key into a value coming from the backend. @@ -61,7 +60,6 @@ friend class IDBValueUnwrapper; - IDBValue(); IDBValue(const WebIDBValue&, v8::Isolate*); IDBValue(scoped_refptr<SharedBuffer>, const WebVector<WebBlobInfo>&,
diff --git a/third_party/WebKit/Source/modules/modules_idl_files.gni b/third_party/WebKit/Source/modules/modules_idl_files.gni index 925c67b..1be666d 100644 --- a/third_party/WebKit/Source/modules/modules_idl_files.gni +++ b/third_party/WebKit/Source/modules/modules_idl_files.gni
@@ -654,6 +654,7 @@ "canvas/htmlcanvas/HTMLCanvasElementModule.idl", "canvas/canvas2d/CanvasPath.idl", "clipboard/NavigatorClipboard.idl", + "cookie_store/ServiceWorkerGlobalScopeCookieStore.idl", "cookie_store/WindowCookieStore.idl", "credentialmanager/CredentialUserData.idl", "credentialmanager/NavigatorCredentials.idl",
diff --git a/third_party/WebKit/Source/modules/serviceworkers/BUILD.gn b/third_party/WebKit/Source/modules/serviceworkers/BUILD.gn index f1797a5..df54e9c 100644 --- a/third_party/WebKit/Source/modules/serviceworkers/BUILD.gn +++ b/third_party/WebKit/Source/modules/serviceworkers/BUILD.gn
@@ -56,6 +56,8 @@ "ServiceWorkerWindowClient.h", "ServiceWorkerWindowClientCallback.cpp", "ServiceWorkerWindowClientCallback.h", + "ThreadSafeScriptContainer.cpp", + "ThreadSafeScriptContainer.h", "WaitUntilObserver.cpp", "WaitUntilObserver.h", ] @@ -63,4 +65,8 @@ public_deps = [ "//third_party/WebKit/Source/platform", ] + + deps = [ + "//base", + ] }
diff --git a/third_party/WebKit/Source/modules/serviceworkers/DEPS b/third_party/WebKit/Source/modules/serviceworkers/DEPS index 3b5a86b..4f9af63 100644 --- a/third_party/WebKit/Source/modules/serviceworkers/DEPS +++ b/third_party/WebKit/Source/modules/serviceworkers/DEPS
@@ -1,10 +1,13 @@ include_rules = [ + "+base/barrier_closure.h", + "+base/threading/thread_checker.h", "-modules", "+modules/EventModules.h", "+modules/EventTargetModules.h", "+modules/ModulesExport.h", "+modules/fetch", "+modules/serviceworkers", + "+mojo/public/cpp/bindings/strong_binding.h", "+mojo/public/cpp/system/data_pipe.h", "+services/network/public/interfaces", ] @@ -18,4 +21,11 @@ "+modules/payments", "+modules/push_messaging", ], + "ServiceWorkerInstalledScriptsManagerTest\.cpp": [ + "+base/run_loop.h", + "+mojo/public/cpp/bindings/binding.h", + ], + "WebEmbeddedWorkerImplTest\.cpp": [ + "+modules/exported", + ], }
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.cpp b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.cpp index 626ca79e..9828e1cf 100644 --- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.cpp +++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.cpp
@@ -7,21 +7,247 @@ #include <memory> #include <utility> +#include "base/barrier_closure.h" +#include "base/threading/thread_checker.h" #include "core/html/parser/TextResourceDecoder.h" #include "modules/serviceworkers/ServiceWorkerThread.h" +#include "mojo/public/cpp/bindings/strong_binding.h" +#include "platform/CrossThreadFunctional.h" +#include "platform/wtf/Functional.h" +#include "platform/wtf/HashMap.h" +#include "platform/wtf/Vector.h" #include "platform/wtf/text/StringBuilder.h" +#include "public/platform/WebURL.h" +#include "public/platform/WebVector.h" namespace blink { +using RawScriptData = ThreadSafeScriptContainer::RawScriptData; + +namespace { + +// Receiver is a class to read a Mojo data pipe. Received data are stored in +// chunks. Lives on the IO thread. Receiver is owned by Internal via +// BundledReceivers. It is created to read the script body or metadata from a +// data pipe, and is destroyed when the read finishes. +class Receiver { + public: + using BytesChunk = WebVector<char>; + + Receiver(mojo::ScopedDataPipeConsumerHandle handle, uint64_t total_bytes) + : handle_(std::move(handle)), + watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL), + remaining_bytes_(total_bytes) {} + + void Start(base::OnceClosure callback) { + if (!handle_.is_valid()) { + std::move(callback).Run(); + return; + } + callback_ = std::move(callback); + // Unretained is safe because |watcher_| is owned by |this|. + MojoResult rv = watcher_.Watch( + handle_.get(), MOJO_HANDLE_SIGNAL_READABLE, + WTF::BindRepeating(&Receiver::OnReadable, WTF::Unretained(this))); + DCHECK_EQ(MOJO_RESULT_OK, rv); + watcher_.ArmOrNotify(); + } + + void OnReadable(MojoResult) { + // It isn't necessary to handle MojoResult here since BeginReadDataRaw() + // returns an equivalent error. + const void* buffer = nullptr; + uint32_t bytes_read = 0; + MojoResult rv = + handle_->BeginReadData(&buffer, &bytes_read, MOJO_READ_DATA_FLAG_NONE); + switch (rv) { + case MOJO_RESULT_BUSY: + case MOJO_RESULT_INVALID_ARGUMENT: + NOTREACHED(); + return; + case MOJO_RESULT_FAILED_PRECONDITION: + // Closed by peer. + OnCompleted(); + return; + case MOJO_RESULT_SHOULD_WAIT: + watcher_.ArmOrNotify(); + return; + case MOJO_RESULT_OK: + break; + default: + // mojo::BeginReadDataRaw() should not return any other values. + // Notify the error to the browser by resetting the handle even though + // it's in the middle of data transfer. + OnCompleted(); + return; + } + + if (bytes_read > 0) + chunks_.emplace_back(static_cast<const char*>(buffer), bytes_read); + + rv = handle_->EndReadData(bytes_read); + DCHECK_EQ(rv, MOJO_RESULT_OK); + CHECK_GE(remaining_bytes_, bytes_read); + remaining_bytes_ -= bytes_read; + watcher_.ArmOrNotify(); + } + + bool is_running() const { return handle_.is_valid(); } + bool has_received_all_data() const { return remaining_bytes_ == 0; } + + WTF::Vector<BytesChunk> TakeChunks() { + DCHECK(!is_running()); + return std::move(chunks_); + } + + private: + void OnCompleted() { + handle_.reset(); + watcher_.Cancel(); + if (!has_received_all_data()) + chunks_.clear(); + DCHECK(callback_); + std::move(callback_).Run(); + } + + base::OnceClosure callback_; + mojo::ScopedDataPipeConsumerHandle handle_; + mojo::SimpleWatcher watcher_; + + WTF::Vector<BytesChunk> chunks_; + uint64_t remaining_bytes_; +}; + +// BundledReceivers is a helper class to wait for the end of reading body and +// meta data. Lives on the IO thread. +class BundledReceivers { + public: + BundledReceivers(mojo::ScopedDataPipeConsumerHandle meta_data_handle, + uint64_t meta_data_size, + mojo::ScopedDataPipeConsumerHandle body_handle, + uint64_t body_size) + : meta_data_(std::move(meta_data_handle), meta_data_size), + body_(std::move(body_handle), body_size) {} + + // Starts reading the pipes and invokes |callback| when both are finished. + void Start(base::OnceClosure callback) { + base::RepeatingClosure wait_all_closure = + base::BarrierClosure(2, std::move(callback)); + meta_data_.Start(wait_all_closure); + body_.Start(wait_all_closure); + } + + Receiver* meta_data() { return &meta_data_; } + Receiver* body() { return &body_; } + + private: + Receiver meta_data_; + Receiver body_; +}; + +// Internal lives on the IO thread. This receives +// mojom::blink::ServiceWorkerScriptInfo for all installed scripts and then +// starts reading the body and meta data from the browser. This instance will be +// kept alive as long as the Mojo's connection is established. +class Internal : public mojom::blink::ServiceWorkerInstalledScriptsManager { + public: + // Called on the IO thread. + // Creates and binds a new Internal instance to |request|. + static void Create( + scoped_refptr<ThreadSafeScriptContainer> script_container, + mojom::blink::ServiceWorkerInstalledScriptsManagerRequest request) { + mojo::MakeStrongBinding( + std::make_unique<Internal>(std::move(script_container)), + std::move(request)); + } + + Internal(scoped_refptr<ThreadSafeScriptContainer> script_container) + : script_container_(std::move(script_container)), weak_factory_(this) {} + + ~Internal() override { + DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_); + // Wake up a waiting thread so it does not wait forever. If the script has + // not been added yet, that means something went wrong. From here, + // script_container_->Wait() will return false if the script hasn't been + // added yet. + script_container_->OnAllDataAddedOnIOThread(); + } + + // Implements mojom::blink::ServiceWorkerInstalledScriptsManager. + // Called on the IO thread. + void TransferInstalledScript( + mojom::blink::ServiceWorkerScriptInfoPtr script_info) override { + DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_); + KURL script_url(script_info->script_url); + auto receivers = std::make_unique<BundledReceivers>( + std::move(script_info->meta_data), script_info->meta_data_size, + std::move(script_info->body), script_info->body_size); + receivers->Start(WTF::Bind(&Internal::OnScriptReceived, + weak_factory_.GetWeakPtr(), + std::move(script_info))); + DCHECK(!running_receivers_.Contains(script_url)); + running_receivers_.insert(script_url, std::move(receivers)); + } + + // Called on the IO thread. + void OnScriptReceived(mojom::blink::ServiceWorkerScriptInfoPtr script_info) { + DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_); + auto iter = running_receivers_.find(script_info->script_url); + DCHECK(iter != running_receivers_.end()); + std::unique_ptr<BundledReceivers> receivers = std::move(iter->value); + DCHECK(receivers); + if (!receivers->body()->has_received_all_data() || + !receivers->meta_data()->has_received_all_data()) { + script_container_->AddOnIOThread(script_info->script_url, + RawScriptData::CreateInvalidInstance()); + running_receivers_.erase(iter); + return; + } + + auto script_data = RawScriptData::Create( + script_info->encoding, receivers->body()->TakeChunks(), + receivers->meta_data()->TakeChunks()); + for (auto it : script_info->headers) { + script_data->AddHeader(it.key, it.value); + } + script_container_->AddOnIOThread(script_info->script_url, + std::move(script_data)); + running_receivers_.erase(iter); + } + + private: + THREAD_CHECKER(io_thread_checker_); + HashMap<KURL, std::unique_ptr<BundledReceivers>> running_receivers_; + scoped_refptr<ThreadSafeScriptContainer> script_container_; + base::WeakPtrFactory<Internal> weak_factory_; +}; + +} // namespace + ServiceWorkerInstalledScriptsManager::ServiceWorkerInstalledScriptsManager( - std::unique_ptr<WebServiceWorkerInstalledScriptsManager> manager) - : manager_(std::move(manager)) { - DCHECK(manager_); + WebVector<WebURL> installed_urls, + mojom::blink::ServiceWorkerInstalledScriptsManagerRequest manager_request, + mojom::blink::ServiceWorkerInstalledScriptsManagerHostPtrInfo + manager_host_ptr, + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) + : script_container_(base::MakeRefCounted<ThreadSafeScriptContainer>()) { + // We're on the main thread now, but |installed_urls_| will be accessed on the + // worker thread later, so make a deep copy of |url| as key. + for (WebURL& url : installed_urls) + installed_urls_.insert(KURL(url).Copy()); + manager_host_ = + mojom::blink::ThreadSafeServiceWorkerInstalledScriptsManagerHostPtr:: + Create(mojom::blink::ServiceWorkerInstalledScriptsManagerHostPtr( + std::move(manager_host_ptr))); + io_task_runner->PostTask( + FROM_HERE, ConvertToBaseCallback( + CrossThreadBind(&Internal::Create, script_container_, + WTF::Passed(std::move(manager_request))))); } bool ServiceWorkerInstalledScriptsManager::IsScriptInstalled( const KURL& script_url) const { - return manager_->IsScriptInstalled(script_url); + return installed_urls_.Contains(script_url); } InstalledScriptsManager::ScriptStatus @@ -30,8 +256,7 @@ InstalledScriptsManager::ScriptData* out_script_data) { DCHECK(!IsMainThread()); // This blocks until the script is received from the browser. - std::unique_ptr<WebServiceWorkerInstalledScriptsManager::RawScriptData> - raw_script_data = manager_->GetRawScriptData(script_url); + std::unique_ptr<RawScriptData> raw_script_data = GetRawScriptData(script_url); DCHECK(raw_script_data); if (!raw_script_data->IsValid()) { *out_script_data = InstalledScriptsManager::ScriptData(); @@ -68,4 +293,38 @@ return ScriptStatus::kSuccess; } +std::unique_ptr<RawScriptData> +ServiceWorkerInstalledScriptsManager::GetRawScriptData(const KURL& script_url) { + if (!IsScriptInstalled(script_url)) + return nullptr; + + ThreadSafeScriptContainer::ScriptStatus status = + script_container_->GetStatusOnWorkerThread(script_url); + // If the script has already been taken, request the browser to send the + // script. + if (status == ThreadSafeScriptContainer::ScriptStatus::kTaken) { + script_container_->ResetOnWorkerThread(script_url); + (*manager_host_)->RequestInstalledScript(script_url); + status = script_container_->GetStatusOnWorkerThread(script_url); + } + + // If the script has not been received at this point, wait for arrival by + // blocking the worker thread. + if (status == ThreadSafeScriptContainer::ScriptStatus::kPending) { + // Wait for arrival of the script. + const bool success = script_container_->WaitOnWorkerThread(script_url); + // It can fail due to an error on Mojo pipes. + if (!success) + return RawScriptData::CreateInvalidInstance(); + status = script_container_->GetStatusOnWorkerThread(script_url); + DCHECK_NE(ThreadSafeScriptContainer::ScriptStatus::kPending, status); + } + + if (status == ThreadSafeScriptContainer::ScriptStatus::kFailed) + return RawScriptData::CreateInvalidInstance(); + DCHECK_EQ(ThreadSafeScriptContainer::ScriptStatus::kReceived, status); + + return script_container_->TakeOnWorkerThread(script_url); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.h b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.h index a6910cd07..71dd1c16 100644 --- a/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.h +++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManager.h
@@ -6,18 +6,30 @@ #define ServiceWorkerInstalledScriptsManager_h #include "core/workers/InstalledScriptsManager.h" -#include "public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h" +#include "modules/ModulesExport.h" +#include "modules/serviceworkers/ThreadSafeScriptContainer.h" +#include "platform/weborigin/KURL.h" +#include "platform/weborigin/KURLHash.h" +#include "platform/wtf/HashSet.h" +#include "public/platform/WebVector.h" +#include "third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom-blink.h" namespace blink { +class WebURL; + // ServiceWorkerInstalledScriptsManager provides the main script and imported // scripts of an installed service worker. The scripts are streamed from the // browser process in parallel with worker thread initialization. -class ServiceWorkerInstalledScriptsManager final +class MODULES_EXPORT ServiceWorkerInstalledScriptsManager : public InstalledScriptsManager { public: - explicit ServiceWorkerInstalledScriptsManager( - std::unique_ptr<WebServiceWorkerInstalledScriptsManager>); + ServiceWorkerInstalledScriptsManager( + WebVector<WebURL> installed_urls, + mojom::blink::ServiceWorkerInstalledScriptsManagerRequest, + mojom::blink::ServiceWorkerInstalledScriptsManagerHostPtrInfo, + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner); + virtual ~ServiceWorkerInstalledScriptsManager() = default; // InstalledScriptsManager implementation. bool IsScriptInstalled(const KURL& script_url) const override; @@ -25,9 +37,18 @@ ScriptData* out_script_data) override; private: - std::unique_ptr<WebServiceWorkerInstalledScriptsManager> manager_; + friend class ServiceWorkerInstalledScriptsManagerTest; + + std::unique_ptr<ThreadSafeScriptContainer::RawScriptData> GetRawScriptData( + const KURL& script_url); + + WTF::HashSet<KURL> installed_urls_; + scoped_refptr<ThreadSafeScriptContainer> script_container_; + scoped_refptr< + mojom::blink::ThreadSafeServiceWorkerInstalledScriptsManagerHostPtr> + manager_host_; }; } // namespace blink -#endif // WorkerInstalledScriptsManager_h +#endif // ServiceWorkerInstalledScriptsManager_h
diff --git a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl_unittest.cc b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManagerTest.cpp similarity index 62% rename from content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl_unittest.cc rename to third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManagerTest.cpp index 5b24150..33582c7 100644 --- a/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl_unittest.cc +++ b/third_party/WebKit/Source/modules/serviceworkers/ServiceWorkerInstalledScriptsManagerTest.cpp
@@ -2,44 +2,53 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h" +#include "modules/serviceworkers/ServiceWorkerInstalledScriptsManager.h" -#include "base/bind.h" -#include "base/message_loop/message_loop.h" +#include <memory> #include "base/run_loop.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread.h" -#include "content/public/test/test_browser_thread_bundle.h" #include "mojo/public/cpp/bindings/binding.h" +#include "platform/CrossThreadFunctional.h" +#include "platform/WaitableEvent.h" +#include "platform/wtf/Functional.h" +#include "public/platform/Platform.h" +#include "public/platform/WebThread.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom-blink.h" -namespace content { +namespace blink { + +namespace { class BrowserSideSender - : blink::mojom::ServiceWorkerInstalledScriptsManagerHost { + : mojom::blink::ServiceWorkerInstalledScriptsManagerHost { public: BrowserSideSender() : binding_(this) {} ~BrowserSideSender() override = default; - blink::mojom::ServiceWorkerInstalledScriptsInfoPtr CreateAndBind( - const std::vector<GURL>& installed_urls) { + mojom::blink::ServiceWorkerInstalledScriptsInfoPtr CreateAndBind( + const WTF::Vector<KURL>& installed_urls) { EXPECT_FALSE(manager_.is_bound()); EXPECT_FALSE(body_handle_.is_valid()); EXPECT_FALSE(meta_data_handle_.is_valid()); - auto scripts_info = blink::mojom::ServiceWorkerInstalledScriptsInfo::New(); + auto scripts_info = mojom::blink::ServiceWorkerInstalledScriptsInfo::New(); scripts_info->installed_urls = installed_urls; scripts_info->manager_request = mojo::MakeRequest(&manager_); binding_.Bind(mojo::MakeRequest(&scripts_info->manager_host_ptr)); return scripts_info; } - void TransferInstalledScript(const GURL& script_url, - int64_t body_size, - int64_t meta_data_size) { + void TransferInstalledScript( + const KURL& script_url, + const WTF::String& encoding, + const WTF::HashMap<WTF::String, WTF::String>& headers, + int64_t body_size, + int64_t meta_data_size) { EXPECT_FALSE(body_handle_.is_valid()); EXPECT_FALSE(meta_data_handle_.is_valid()); - auto script_info = blink::mojom::ServiceWorkerScriptInfo::New(); + auto script_info = mojom::blink::ServiceWorkerScriptInfo::New(); script_info->script_url = script_url; + script_info->encoding = encoding; + script_info->headers = headers; EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(nullptr, &body_handle_, &script_info->body)); EXPECT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(nullptr, &meta_data_handle_, @@ -63,7 +72,7 @@ void ResetManager() { manager_.reset(); } - void WaitForRequestInstalledScript(const GURL& script_url) { + void WaitForRequestInstalledScript(const KURL& script_url) { waiting_requested_url_ = script_url; base::RunLoop loop; requested_script_closure_ = loop.QuitClosure(); @@ -71,7 +80,7 @@ } private: - void RequestInstalledScript(const GURL& script_url) override { + void RequestInstalledScript(const KURL& script_url) override { EXPECT_EQ(waiting_requested_url_, script_url); ASSERT_TRUE(requested_script_closure_); std::move(requested_script_closure_).Run(); @@ -89,10 +98,10 @@ } base::OnceClosure requested_script_closure_; - GURL waiting_requested_url_; + KURL waiting_requested_url_; - blink::mojom::ServiceWorkerInstalledScriptsManagerPtr manager_; - mojo::Binding<blink::mojom::ServiceWorkerInstalledScriptsManagerHost> + mojom::blink::ServiceWorkerInstalledScriptsManagerPtr manager_; + mojo::Binding<mojom::blink::ServiceWorkerInstalledScriptsManagerHost> binding_; mojo::ScopedDataPipeProducerHandle body_handle_; @@ -101,96 +110,93 @@ DISALLOW_COPY_AND_ASSIGN(BrowserSideSender); }; -class WebServiceWorkerInstalledScriptsManagerImplTest : public testing::Test { +CrossThreadHTTPHeaderMapData ToCrossThreadHTTPHeaderMapData( + const WTF::HashMap<WTF::String, WTF::String>& headers) { + CrossThreadHTTPHeaderMapData data; + for (auto it : headers) + data.emplace_back(it.key, it.value); + return data; +} + +} // namespace + +class ServiceWorkerInstalledScriptsManagerTest : public testing::Test { public: - WebServiceWorkerInstalledScriptsManagerImplTest() - : io_thread_("io thread"), - worker_thread_("worker thread"), - worker_waiter_(base::WaitableEvent::ResetPolicy::AUTOMATIC, - base::WaitableEvent::InitialState::NOT_SIGNALED) {} + ServiceWorkerInstalledScriptsManagerTest() + : io_thread_(Platform::Current()->CreateThread("io thread")), + worker_thread_(Platform::Current()->CreateThread("worker thread")), + io_task_runner_(io_thread_->GetSingleThreadTaskRunner()), + worker_task_runner_(worker_thread_->GetSingleThreadTaskRunner()) {} protected: - using RawScriptData = - blink::WebServiceWorkerInstalledScriptsManager::RawScriptData; - - void SetUp() override { - ASSERT_TRUE(io_thread_.Start()); - ASSERT_TRUE(worker_thread_.Start()); - io_task_runner_ = io_thread_.task_runner(); - worker_task_runner_ = worker_thread_.task_runner(); - } - - void TearDown() override { - io_thread_.Stop(); - worker_thread_.Stop(); - } + using RawScriptData = ThreadSafeScriptContainer::RawScriptData; void CreateInstalledScriptsManager( - blink::mojom::ServiceWorkerInstalledScriptsInfoPtr + mojom::blink::ServiceWorkerInstalledScriptsInfoPtr installed_scripts_info) { installed_scripts_manager_ = - WebServiceWorkerInstalledScriptsManagerImpl::Create( - std::move(installed_scripts_info), io_task_runner_); + std::make_unique<ServiceWorkerInstalledScriptsManager>( + std::move(installed_scripts_info->installed_urls), + std::move(installed_scripts_info->manager_request), + std::move(installed_scripts_info->manager_host_ptr), + io_task_runner_); } - base::WaitableEvent* IsScriptInstalledOnWorkerThread(const GURL& script_url, - bool* out_installed) { + WaitableEvent* IsScriptInstalledOnWorkerThread(const KURL& script_url, + bool* out_installed) { worker_task_runner_->PostTask( FROM_HERE, - base::BindOnce( - [](blink::WebServiceWorkerInstalledScriptsManager* - installed_scripts_manager, - const blink::WebURL& script_url, bool* out_installed, - base::WaitableEvent* waiter) { + ConvertToBaseCallback(CrossThreadBind( + [](ServiceWorkerInstalledScriptsManager* installed_scripts_manager, + const KURL& script_url, bool* out_installed, + WaitableEvent* waiter) { *out_installed = installed_scripts_manager->IsScriptInstalled(script_url); waiter->Signal(); }, - installed_scripts_manager_.get(), script_url, out_installed, - &worker_waiter_)); + CrossThreadUnretained(installed_scripts_manager_.get()), script_url, + CrossThreadUnretained(out_installed), + CrossThreadUnretained(&worker_waiter_)))); return &worker_waiter_; } - base::WaitableEvent* GetRawScriptDataOnWorkerThread( - const GURL& script_url, + WaitableEvent* GetRawScriptDataOnWorkerThread( + const KURL& script_url, std::unique_ptr<RawScriptData>* out_data) { worker_task_runner_->PostTask( FROM_HERE, - base::BindOnce( - [](blink::WebServiceWorkerInstalledScriptsManager* - installed_scripts_manager, - const blink::WebURL& script_url, - std::unique_ptr<RawScriptData>* out_data, - base::WaitableEvent* waiter) { - *out_data = - installed_scripts_manager->GetRawScriptData(script_url); - waiter->Signal(); - }, - installed_scripts_manager_.get(), script_url, out_data, - &worker_waiter_)); + ConvertToBaseCallback(CrossThreadBind( + &ServiceWorkerInstalledScriptsManagerTest::CallGetRawScriptData, + CrossThreadUnretained(this), script_url, + CrossThreadUnretained(out_data), + CrossThreadUnretained(&worker_waiter_)))); return &worker_waiter_; } private: - // Provides SingleThreadTaskRunner for this test. - const base::MessageLoop message_loop_; + void CallGetRawScriptData(const KURL& script_url, + std::unique_ptr<RawScriptData>* out_data, + WaitableEvent* waiter) { + *out_data = installed_scripts_manager_->GetRawScriptData(script_url); + waiter->Signal(); + } - base::Thread io_thread_; - base::Thread worker_thread_; + std::unique_ptr<WebThread> io_thread_; + std::unique_ptr<WebThread> worker_thread_; scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner_; - base::WaitableEvent worker_waiter_; + WaitableEvent worker_waiter_; - std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManager> + std::unique_ptr<ServiceWorkerInstalledScriptsManager> installed_scripts_manager_; - DISALLOW_COPY_AND_ASSIGN(WebServiceWorkerInstalledScriptsManagerImplTest); + DISALLOW_COPY_AND_ASSIGN(ServiceWorkerInstalledScriptsManagerTest); }; -TEST_F(WebServiceWorkerInstalledScriptsManagerImplTest, GetRawScriptData) { - const GURL kScriptUrl = GURL("https://example.com/installed1.js"); - const GURL kUnknownScriptUrl = GURL("https://example.com/not_installed.js"); +TEST_F(ServiceWorkerInstalledScriptsManagerTest, GetRawScriptData) { + const KURL kScriptUrl("https://example.com/installed1.js"); + const KURL kUnknownScriptUrl("https://example.com/not_installed.js"); BrowserSideSender sender; CreateInstalledScriptsManager(sender.CreateAndBind({kScriptUrl})); @@ -215,11 +221,16 @@ std::unique_ptr<RawScriptData> script_data; const std::string kExpectedBody = "This is a script body."; const std::string kExpectedMetaData = "This is a meta data."; - base::WaitableEvent* get_raw_script_data_waiter = + const WTF::String kScriptInfoEncoding("utf8"); + const WTF::HashMap<WTF::String, WTF::String> kScriptInfoHeaders( + {{"Cache-Control", "no-cache"}, {"User-Agent", "Chrome"}}); + + WaitableEvent* get_raw_script_data_waiter = GetRawScriptDataOnWorkerThread(kScriptUrl, &script_data); // Start transferring the script. +1 for null terminator. - sender.TransferInstalledScript(kScriptUrl, kExpectedBody.size() + 1, + sender.TransferInstalledScript(kScriptUrl, kScriptInfoEncoding, + kScriptInfoHeaders, kExpectedBody.size() + 1, kExpectedMetaData.size() + 1); sender.PushBody(kExpectedBody); sender.PushMetaData(kExpectedMetaData); @@ -243,22 +254,29 @@ script_data->MetaDataChunks()[0].size()); EXPECT_STREQ(kExpectedMetaData.data(), script_data->MetaDataChunks()[0].Data()); + EXPECT_EQ(kScriptInfoEncoding, script_data->Encoding()); + EXPECT_EQ(ToCrossThreadHTTPHeaderMapData(kScriptInfoHeaders), + *(script_data->TakeHeaders())); } { std::unique_ptr<RawScriptData> script_data; const std::string kExpectedBody = "This is another script body."; const std::string kExpectedMetaData = "This is another meta data."; + const WTF::String kScriptInfoEncoding("ASCII"); + const WTF::HashMap<WTF::String, WTF::String> kScriptInfoHeaders( + {{"Connection", "keep-alive"}, {"Content-Length", "512"}}); // Request the same script again. - base::WaitableEvent* get_raw_script_data_waiter = + WaitableEvent* get_raw_script_data_waiter = GetRawScriptDataOnWorkerThread(kScriptUrl, &script_data); // It should call a Mojo IPC "RequestInstalledScript()" to the browser. sender.WaitForRequestInstalledScript(kScriptUrl); // Start transferring the script. +1 for null terminator. - sender.TransferInstalledScript(kScriptUrl, kExpectedBody.size() + 1, + sender.TransferInstalledScript(kScriptUrl, kScriptInfoEncoding, + kScriptInfoHeaders, kExpectedBody.size() + 1, kExpectedMetaData.size() + 1); sender.PushBody(kExpectedBody); sender.PushMetaData(kExpectedMetaData); @@ -282,13 +300,15 @@ script_data->MetaDataChunks()[0].size()); EXPECT_STREQ(kExpectedMetaData.data(), script_data->MetaDataChunks()[0].Data()); + EXPECT_EQ(kScriptInfoEncoding, script_data->Encoding()); + EXPECT_EQ(ToCrossThreadHTTPHeaderMapData(kScriptInfoHeaders), + *(script_data->TakeHeaders())); } } -TEST_F(WebServiceWorkerInstalledScriptsManagerImplTest, - EarlyDisconnectionBody) { - const GURL kScriptUrl = GURL("https://example.com/installed1.js"); - const GURL kUnknownScriptUrl = GURL("https://example.com/not_installed.js"); +TEST_F(ServiceWorkerInstalledScriptsManagerTest, EarlyDisconnectionBody) { + const KURL kScriptUrl("https://example.com/installed1.js"); + const KURL kUnknownScriptUrl("https://example.com/not_installed.js"); BrowserSideSender sender; CreateInstalledScriptsManager(sender.CreateAndBind({kScriptUrl})); @@ -297,14 +317,16 @@ std::unique_ptr<RawScriptData> script_data; const std::string kExpectedBody = "This is a script body."; const std::string kExpectedMetaData = "This is a meta data."; - base::WaitableEvent* get_raw_script_data_waiter = + WaitableEvent* get_raw_script_data_waiter = GetRawScriptDataOnWorkerThread(kScriptUrl, &script_data); // Start transferring the script. // Body is expected to be 100 bytes larger than kExpectedBody, but sender // only sends kExpectedBody and a null byte (kExpectedBody.size() + 1 bytes // in total). - sender.TransferInstalledScript(kScriptUrl, kExpectedBody.size() + 100, + sender.TransferInstalledScript(kScriptUrl, WTF::String::FromUTF8("utf8"), + WTF::HashMap<WTF::String, WTF::String>(), + kExpectedBody.size() + 100, kExpectedMetaData.size() + 1); sender.PushBody(kExpectedBody); sender.PushMetaData(kExpectedMetaData); @@ -332,10 +354,9 @@ } } -TEST_F(WebServiceWorkerInstalledScriptsManagerImplTest, - EarlyDisconnectionMetaData) { - const GURL kScriptUrl = GURL("https://example.com/installed1.js"); - const GURL kUnknownScriptUrl = GURL("https://example.com/not_installed.js"); +TEST_F(ServiceWorkerInstalledScriptsManagerTest, EarlyDisconnectionMetaData) { + const KURL kScriptUrl("https://example.com/installed1.js"); + const KURL kUnknownScriptUrl("https://example.com/not_installed.js"); BrowserSideSender sender; CreateInstalledScriptsManager(sender.CreateAndBind({kScriptUrl})); @@ -344,14 +365,16 @@ std::unique_ptr<RawScriptData> script_data; const std::string kExpectedBody = "This is a script body."; const std::string kExpectedMetaData = "This is a meta data."; - base::WaitableEvent* get_raw_script_data_waiter = + WaitableEvent* get_raw_script_data_waiter = GetRawScriptDataOnWorkerThread(kScriptUrl, &script_data); // Start transferring the script. // Meta data is expected to be 100 bytes larger than kExpectedMetaData, but // sender only sends kExpectedMetaData and a null byte // (kExpectedMetaData.size() + 1 bytes in total). - sender.TransferInstalledScript(kScriptUrl, kExpectedBody.size() + 1, + sender.TransferInstalledScript(kScriptUrl, WTF::String::FromUTF8("utf8"), + WTF::HashMap<WTF::String, WTF::String>(), + kExpectedBody.size() + 1, kExpectedMetaData.size() + 100); sender.PushBody(kExpectedBody); sender.PushMetaData(kExpectedMetaData); @@ -379,17 +402,16 @@ } } -TEST_F(WebServiceWorkerInstalledScriptsManagerImplTest, - EarlyDisconnectionManager) { - const GURL kScriptUrl = GURL("https://example.com/installed1.js"); - const GURL kUnknownScriptUrl = GURL("https://example.com/not_installed.js"); +TEST_F(ServiceWorkerInstalledScriptsManagerTest, EarlyDisconnectionManager) { + const KURL kScriptUrl("https://example.com/installed1.js"); + const KURL kUnknownScriptUrl("https://example.com/not_installed.js"); BrowserSideSender sender; CreateInstalledScriptsManager(sender.CreateAndBind({kScriptUrl})); { std::unique_ptr<RawScriptData> script_data; - base::WaitableEvent* get_raw_script_data_waiter = + WaitableEvent* get_raw_script_data_waiter = GetRawScriptDataOnWorkerThread(kScriptUrl, &script_data); // Reset the Mojo connection before sending the script. @@ -414,4 +436,4 @@ } } -} // namespace content +} // namespace blink
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ThreadSafeScriptContainer.cpp b/third_party/WebKit/Source/modules/serviceworkers/ThreadSafeScriptContainer.cpp new file mode 100644 index 0000000..ccbe7bbf --- /dev/null +++ b/third_party/WebKit/Source/modules/serviceworkers/ThreadSafeScriptContainer.cpp
@@ -0,0 +1,119 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "modules/serviceworkers/ThreadSafeScriptContainer.h" + +namespace blink { + +// static +std::unique_ptr<ThreadSafeScriptContainer::RawScriptData> +ThreadSafeScriptContainer::RawScriptData::Create( + const WTF::String& encoding, + WTF::Vector<BytesChunk> script_text, + WTF::Vector<BytesChunk> meta_data) { + return WTF::WrapUnique(new RawScriptData(encoding, std::move(script_text), + std::move(meta_data), + true /* is_valid */)); +} + +// static +std::unique_ptr<ThreadSafeScriptContainer::RawScriptData> +ThreadSafeScriptContainer::RawScriptData::CreateInvalidInstance() { + return WTF::WrapUnique( + new RawScriptData(WTF::String() /* encoding */, WTF::Vector<BytesChunk>(), + WTF::Vector<BytesChunk>(), false /* is_valid */)); +} + +ThreadSafeScriptContainer::RawScriptData::RawScriptData( + const WTF::String& encoding, + WTF::Vector<BytesChunk> script_text, + WTF::Vector<BytesChunk> meta_data, + bool is_valid) + : is_valid_(is_valid), + encoding_(encoding.IsolatedCopy()), + script_text_(std::move(script_text)), + meta_data_(std::move(meta_data)), + headers_(std::make_unique<CrossThreadHTTPHeaderMapData>()) {} + +ThreadSafeScriptContainer::RawScriptData::~RawScriptData() = default; + +void ThreadSafeScriptContainer::RawScriptData::AddHeader( + const WTF::String& key, + const WTF::String& value) { + headers_->emplace_back(key.IsolatedCopy(), value.IsolatedCopy()); +} + +ThreadSafeScriptContainer::ThreadSafeScriptContainer() + : are_all_data_added_(false) {} + +void ThreadSafeScriptContainer::AddOnIOThread( + const KURL& url, + std::unique_ptr<RawScriptData> data) { + WTF::MutexLocker locker(mutex_); + DCHECK(!script_data_.Contains(url)); + // |script_data_| is also accessed on the worker thread, so make a deep copy + // of |url| as key. + script_data_.insert(url.Copy(), std::move(data)); + if (url == waiting_url_) + waiting_cv_.Signal(); +} + +ThreadSafeScriptContainer::ScriptStatus +ThreadSafeScriptContainer::GetStatusOnWorkerThread(const KURL& url) { + WTF::MutexLocker locker(mutex_); + auto it = script_data_.find(url); + if (it == script_data_.end()) + return ScriptStatus::kPending; + if (!it->value) + return ScriptStatus::kTaken; + if (!it->value->IsValid()) + return ScriptStatus::kFailed; + return ScriptStatus::kReceived; +} + +void ThreadSafeScriptContainer::ResetOnWorkerThread(const KURL& url) { + WTF::MutexLocker locker(mutex_); + script_data_.erase(url); +} + +bool ThreadSafeScriptContainer::WaitOnWorkerThread(const KURL& url) { + WTF::MutexLocker locker(mutex_); + DCHECK(waiting_url_.IsEmpty()) + << "The script container is unexpectedly shared among worker threads."; + waiting_url_ = url; + while (script_data_.find(url) == script_data_.end()) { + // If waiting script hasn't been added yet though all data are received, + // that means something went wrong. + if (are_all_data_added_) { + waiting_url_ = KURL(); + return false; + } + // This is possible to be waken up spuriously, so that it's necessary to + // check if the entry is really added. + waiting_cv_.Wait(mutex_); + } + waiting_url_ = KURL(); + // TODO(shimazu): Keep the status for each entries instead of using IsValid(). + const auto& data = script_data_.at(url); + // Returns true if |data| has already been taken or is valid. + return !data || data->IsValid(); +} + +std::unique_ptr<ThreadSafeScriptContainer::RawScriptData> +ThreadSafeScriptContainer::TakeOnWorkerThread(const KURL& url) { + WTF::MutexLocker locker(mutex_); + DCHECK(script_data_.Contains(url)) + << "Script should be added before calling Take."; + return std::move(script_data_.find(url)->value); +} + +void ThreadSafeScriptContainer::OnAllDataAddedOnIOThread() { + WTF::MutexLocker locker(mutex_); + are_all_data_added_ = true; + waiting_cv_.Broadcast(); +} + +ThreadSafeScriptContainer::~ThreadSafeScriptContainer() = default; + +} // namespace blink
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ThreadSafeScriptContainer.h b/third_party/WebKit/Source/modules/serviceworkers/ThreadSafeScriptContainer.h new file mode 100644 index 0000000..6aa54139 --- /dev/null +++ b/third_party/WebKit/Source/modules/serviceworkers/ThreadSafeScriptContainer.h
@@ -0,0 +1,151 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ThreadSafeScriptContainer_h +#define ThreadSafeScriptContainer_h + +#include <memory> + +#include "modules/ModulesExport.h" +#include "platform/network/HTTPHeaderMap.h" +#include "platform/weborigin/KURL.h" +#include "platform/weborigin/KURLHash.h" +#include "platform/wtf/HashMap.h" +#include "platform/wtf/ThreadSafeRefCounted.h" +#include "platform/wtf/ThreadingPrimitives.h" +#include "platform/wtf/Vector.h" +#include "platform/wtf/text/WTFString.h" +#include "public/platform/WebVector.h" + +namespace blink { + +// ThreadSafeScriptContainer stores the scripts of a service worker for +// startup. This container is created for each service worker. The IO thread +// adds scripts to the container, and the worker thread takes the scripts. +// +// This class uses explicit synchronization because it needs to support +// synchronous importScripts() from the worker thread. +// +// This class is ThreadSafeRefCounted because there is no ordering guarantee of +// lifetime of its owners, i.e. ServiceWorkerInstalledScriptsManager and its +// Internal class. ServiceWorkerInstalledScriptsManager is destroyed earlier +// than Internal if the worker is terminated before all scripts are streamed, +// and Internal is destroyed earlier if all of scripts are received before +// finishing script evaluation. +class MODULES_EXPORT ThreadSafeScriptContainer final + : public WTF::ThreadSafeRefCounted<ThreadSafeScriptContainer> { + public: + // TODO(leonhsl): Eliminate RawScriptData struct and use + // InstalledScriptsManager::ScriptData directly. + using BytesChunk = WebVector<char>; + + // Container of a script. All the fields of this class need to be + // cross-thread-transfer-safe. + class MODULES_EXPORT RawScriptData { + public: + static std::unique_ptr<RawScriptData> Create( + const WTF::String& encoding, + WTF::Vector<BytesChunk> script_text, + WTF::Vector<BytesChunk> meta_data); + static std::unique_ptr<RawScriptData> CreateInvalidInstance(); + + ~RawScriptData(); + + void AddHeader(const WTF::String& key, const WTF::String& value); + + // Returns false if it fails to receive the script from the browser. + bool IsValid() const { return is_valid_; } + // The encoding of the script text. + const WTF::String& Encoding() const { + DCHECK(is_valid_); + return encoding_; + } + // An array of raw byte chunks of the script text. + const WTF::Vector<BytesChunk>& ScriptTextChunks() const { + DCHECK(is_valid_); + return script_text_; + } + // An array of raw byte chunks of the scripts's meta data from the script's + // V8 code cache. + const WTF::Vector<BytesChunk>& MetaDataChunks() const { + DCHECK(is_valid_); + return meta_data_; + } + + // The HTTP headers of the script. + std::unique_ptr<CrossThreadHTTPHeaderMapData> TakeHeaders() { + DCHECK(is_valid_); + return std::move(headers_); + } + + private: + RawScriptData(const WTF::String& encoding, + WTF::Vector<BytesChunk> script_text, + WTF::Vector<BytesChunk> meta_data, + bool is_valid); + const bool is_valid_; + WTF::String encoding_; + WTF::Vector<BytesChunk> script_text_; + WTF::Vector<BytesChunk> meta_data_; + std::unique_ptr<CrossThreadHTTPHeaderMapData> headers_; + }; + + REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE(); + ThreadSafeScriptContainer(); + + enum class ScriptStatus { + // The script data has been received. + kReceived, + // The script data has been received but it has already been taken. + kTaken, + // Receiving the script has failed. + kFailed, + // The script data has not been received yet. + kPending + }; + + // Called on the IO thread. + void AddOnIOThread(const KURL& script_url, + std::unique_ptr<RawScriptData> raw_data); + + // Called on the worker thread. + ScriptStatus GetStatusOnWorkerThread(const KURL& script_url); + + // Removes the script. After calling this, ScriptStatus for the + // script will be kPending. + // Called on the worker thread. + void ResetOnWorkerThread(const KURL& script_url); + + // Waits until the script is added. The thread is blocked until the script is + // available or receiving the script fails. Returns false if an error happens + // and the waiting script won't be available forever. + // Called on the worker thread. + bool WaitOnWorkerThread(const KURL& script_url); + + // Called on the worker thread. + std::unique_ptr<RawScriptData> TakeOnWorkerThread(const KURL& script_url); + + // Called if no more data will be added. + // Called on the IO thread. + void OnAllDataAddedOnIOThread(); + + private: + friend class WTF::ThreadSafeRefCounted<ThreadSafeScriptContainer>; + ~ThreadSafeScriptContainer(); + + // |mutex_| protects |waiting_cv_|, |script_data_|, |waiting_url_| and + // |are_all_data_added_|. + WTF::Mutex mutex_; + // |waiting_cv_| is signaled when a script whose url matches to |waiting_url| + // is added, or OnAllDataAdded is called. The worker thread waits on this, and + // the IO thread signals it. + ThreadCondition waiting_cv_; + WTF::HashMap<KURL, std::unique_ptr<RawScriptData>> script_data_; + KURL waiting_url_; + bool are_all_data_added_; +}; + +} // namespace blink + +#endif // ThreadSafeScriptContainer_h
diff --git a/third_party/WebKit/Source/modules/serviceworkers/ThreadSafeScriptContainerTest.cpp b/third_party/WebKit/Source/modules/serviceworkers/ThreadSafeScriptContainerTest.cpp new file mode 100644 index 0000000..d0c59d7 --- /dev/null +++ b/third_party/WebKit/Source/modules/serviceworkers/ThreadSafeScriptContainerTest.cpp
@@ -0,0 +1,219 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "modules/serviceworkers/ThreadSafeScriptContainer.h" + +#include <memory> +#include "platform/CrossThreadFunctional.h" +#include "platform/WaitableEvent.h" +#include "platform/wtf/Functional.h" +#include "public/platform/Platform.h" +#include "public/platform/WebThread.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace blink { + +using ScriptStatus = ThreadSafeScriptContainer::ScriptStatus; + +class ThreadSafeScriptContainerTest : public ::testing::Test { + public: + ThreadSafeScriptContainerTest() + : writer_thread_(Platform::Current()->CreateThread("writer_thread")), + reader_thread_(Platform::Current()->CreateThread("reader_thread")), + writer_task_runner_(writer_thread_->GetSingleThreadTaskRunner()), + reader_task_runner_(reader_thread_->GetSingleThreadTaskRunner()), + container_(base::MakeRefCounted<ThreadSafeScriptContainer>()) {} + + protected: + WaitableEvent* AddOnWriterThread( + const KURL& url, + ThreadSafeScriptContainer::RawScriptData** out_data) { + writer_task_runner_->PostTask( + FROM_HERE, + ConvertToBaseCallback(CrossThreadBind( + [](scoped_refptr<ThreadSafeScriptContainer> container, + const KURL& url, + ThreadSafeScriptContainer::RawScriptData** out_data, + WaitableEvent* waiter) { + auto data = ThreadSafeScriptContainer::RawScriptData::Create( + WTF::String::FromUTF8("utf-8") /* encoding */, + WTF::Vector<WebVector<char>>() /* script_text */, + WTF::Vector<WebVector<char>>() /* meta_data */); + *out_data = data.get(); + container->AddOnIOThread(url, std::move(data)); + waiter->Signal(); + }, + container_, url, CrossThreadUnretained(out_data), + CrossThreadUnretained(&writer_waiter_)))); + return &writer_waiter_; + } + + WaitableEvent* OnAllDataAddedOnWriterThread() { + writer_task_runner_->PostTask( + FROM_HERE, ConvertToBaseCallback(CrossThreadBind( + [](scoped_refptr<ThreadSafeScriptContainer> container, + WaitableEvent* waiter) { + container->OnAllDataAddedOnIOThread(); + waiter->Signal(); + }, + container_, CrossThreadUnretained(&writer_waiter_)))); + return &writer_waiter_; + } + + WaitableEvent* GetStatusOnReaderThread(const KURL& url, + ScriptStatus* out_status) { + reader_task_runner_->PostTask( + FROM_HERE, ConvertToBaseCallback(CrossThreadBind( + [](scoped_refptr<ThreadSafeScriptContainer> container, + const KURL& url, ScriptStatus* out_status, + WaitableEvent* waiter) { + *out_status = container->GetStatusOnWorkerThread(url); + waiter->Signal(); + }, + container_, url, CrossThreadUnretained(out_status), + CrossThreadUnretained(&reader_waiter_)))); + return &reader_waiter_; + } + + WaitableEvent* WaitOnReaderThread(const KURL& url, bool* out_exists) { + reader_task_runner_->PostTask( + FROM_HERE, + ConvertToBaseCallback(CrossThreadBind( + [](scoped_refptr<ThreadSafeScriptContainer> container, + const KURL& url, bool* out_exists, WaitableEvent* waiter) { + *out_exists = container->WaitOnWorkerThread(url); + waiter->Signal(); + }, + container_, url, CrossThreadUnretained(out_exists), + CrossThreadUnretained(&reader_waiter_)))); + return &reader_waiter_; + } + + WaitableEvent* TakeOnReaderThread( + const KURL& url, + ThreadSafeScriptContainer::RawScriptData** out_data) { + reader_task_runner_->PostTask( + FROM_HERE, ConvertToBaseCallback(CrossThreadBind( + [](scoped_refptr<ThreadSafeScriptContainer> container, + const KURL& url, + ThreadSafeScriptContainer::RawScriptData** out_data, + WaitableEvent* waiter) { + auto data = container->TakeOnWorkerThread(url); + *out_data = data.get(); + waiter->Signal(); + }, + container_, url, CrossThreadUnretained(out_data), + CrossThreadUnretained(&reader_waiter_)))); + return &reader_waiter_; + } + + private: + std::unique_ptr<WebThread> writer_thread_; + std::unique_ptr<WebThread> reader_thread_; + + scoped_refptr<base::SingleThreadTaskRunner> writer_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> reader_task_runner_; + + WaitableEvent writer_waiter_; + WaitableEvent reader_waiter_; + + scoped_refptr<ThreadSafeScriptContainer> container_; +}; + +TEST_F(ThreadSafeScriptContainerTest, WaitExistingKey) { + const KURL kKey("https://example.com/key"); + { + ScriptStatus result = ScriptStatus::kReceived; + GetStatusOnReaderThread(kKey, &result)->Wait(); + EXPECT_EQ(ScriptStatus::kPending, result); + } + + ThreadSafeScriptContainer::RawScriptData* added_data; + { + bool result = false; + WaitableEvent* pending_wait = WaitOnReaderThread(kKey, &result); + // This should not be signaled until data is added. + EXPECT_FALSE(pending_wait->IsSignaled()); + WaitableEvent* pending_write = AddOnWriterThread(kKey, &added_data); + pending_wait->Wait(); + pending_write->Wait(); + EXPECT_TRUE(result); + } + + { + ScriptStatus result = ScriptStatus::kFailed; + GetStatusOnReaderThread(kKey, &result)->Wait(); + EXPECT_EQ(ScriptStatus::kReceived, result); + } + + { + ThreadSafeScriptContainer::RawScriptData* taken_data; + TakeOnReaderThread(kKey, &taken_data)->Wait(); + EXPECT_EQ(added_data, taken_data); + } + + { + ScriptStatus result = ScriptStatus::kFailed; + GetStatusOnReaderThread(kKey, &result)->Wait(); + // The record of |kKey| should be exist though it's already taken. + EXPECT_EQ(ScriptStatus::kTaken, result); + } + + { + bool result = false; + WaitOnReaderThread(kKey, &result)->Wait(); + // Waiting for |kKey| should succeed. + EXPECT_TRUE(result); + + ThreadSafeScriptContainer::RawScriptData* taken_data; + TakeOnReaderThread(kKey, &taken_data)->Wait(); + // |taken_data| should be nullptr because it's already taken. + EXPECT_EQ(nullptr, taken_data); + } + + // Finish adding data. + OnAllDataAddedOnWriterThread()->Wait(); + + { + bool result = false; + WaitOnReaderThread(kKey, &result)->Wait(); + // The record has been already added, so Wait shouldn't fail. + EXPECT_TRUE(result); + + ThreadSafeScriptContainer::RawScriptData* taken_data; + TakeOnReaderThread(kKey, &taken_data)->Wait(); + // |taken_data| should be nullptr because it's already taken. + EXPECT_EQ(nullptr, taken_data); + } +} + +TEST_F(ThreadSafeScriptContainerTest, WaitNonExistingKey) { + const KURL kKey("https://example.com/key"); + { + ScriptStatus result = ScriptStatus::kReceived; + GetStatusOnReaderThread(kKey, &result)->Wait(); + EXPECT_EQ(ScriptStatus::kPending, result); + } + + { + bool result = true; + WaitableEvent* pending_wait = WaitOnReaderThread(kKey, &result); + // This should not be signaled until OnAllDataAdded is called. + EXPECT_FALSE(pending_wait->IsSignaled()); + WaitableEvent* pending_on_all_data_added = OnAllDataAddedOnWriterThread(); + pending_wait->Wait(); + pending_on_all_data_added->Wait(); + // Aborted wait should return false. + EXPECT_FALSE(result); + } + + { + bool result = true; + WaitOnReaderThread(kKey, &result)->Wait(); + // Wait fails immediately because OnAllDataAdded is called. + EXPECT_FALSE(result); + } +} + +} // namespace blink
diff --git a/third_party/WebKit/Source/modules/serviceworkers/WebEmbeddedWorkerImplTest.cpp b/third_party/WebKit/Source/modules/serviceworkers/WebEmbeddedWorkerImplTest.cpp index 88ba321..f1bb619 100644 --- a/third_party/WebKit/Source/modules/serviceworkers/WebEmbeddedWorkerImplTest.cpp +++ b/third_party/WebKit/Source/modules/serviceworkers/WebEmbeddedWorkerImplTest.cpp
@@ -5,6 +5,9 @@ #include "public/web/WebEmbeddedWorker.h" #include <memory> +#include "modules/exported/WebEmbeddedWorkerImpl.h" +#include "modules/serviceworkers/ServiceWorkerInstalledScriptsManager.h" +#include "modules/serviceworkers/ThreadSafeScriptContainer.h" #include "platform/WaitableEvent.h" #include "platform/WebTaskRunner.h" #include "platform/loader/fetch/ResourceError.h" @@ -16,7 +19,6 @@ #include "public/platform/WebContentSettingsClient.h" #include "public/platform/WebURLLoaderMockFactory.h" #include "public/platform/WebURLResponse.h" -#include "public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h" #include "public/platform/modules/serviceworker/WebServiceWorkerNetworkProvider.h" #include "public/platform/modules/serviceworker/WebServiceWorkerProvider.h" #include "public/web/WebEmbeddedWorkerStartData.h" @@ -25,6 +27,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/WebKit/common/message_port/message_port_channel.h" +#include "third_party/WebKit/common/service_worker/service_worker_installed_scripts_manager.mojom-blink.h" namespace blink { namespace { @@ -104,11 +107,26 @@ }; class MockServiceWorkerInstalledScriptsManager - : public WebServiceWorkerInstalledScriptsManager { + : public ServiceWorkerInstalledScriptsManager { public: - MOCK_CONST_METHOD1(IsScriptInstalled, bool(const WebURL& script_url)); + MockServiceWorkerInstalledScriptsManager() + : ServiceWorkerInstalledScriptsManager( + WebVector<WebURL>() /* installed_urls */, + mojom::blink::ServiceWorkerInstalledScriptsManagerRequest( + mojo::MessagePipe().handle1), + mojom::blink::ServiceWorkerInstalledScriptsManagerHostPtrInfo( + mojo::MessagePipe().handle0, + mojom::blink::ServiceWorkerInstalledScriptsManagerHost:: + Version_), + // Pass a temporary task runner to ensure + // ServiceWorkerInstalledScriptsManager construction succeeds. + Platform::Current() + ->CreateThread("io thread") + ->GetSingleThreadTaskRunner()){}; + MOCK_CONST_METHOD1(IsScriptInstalled, bool(const KURL& script_url)); MOCK_METHOD1(GetRawScriptData, - std::unique_ptr<RawScriptData>(const WebURL& script_url)); + std::unique_ptr<ThreadSafeScriptContainer::RawScriptData>( + const KURL& script_url)); }; class WebEmbeddedWorkerImplTest : public ::testing::Test { @@ -123,9 +141,8 @@ } else { mock_installed_scripts_manager_ = nullptr; } - worker_ = WebEmbeddedWorker::Create( - std::move(client), std::move(installed_scripts_manager), - mojo::ScopedMessagePipeHandle(), mojo::ScopedMessagePipeHandle()); + worker_ = WebEmbeddedWorkerImpl::CreateForTesting( + std::move(client), std::move(installed_scripts_manager)); WebURL script_url = URLTestHelpers::ToKURL("https://www.example.com/sw.js"); WebURLResponse response; @@ -152,7 +169,7 @@ WebEmbeddedWorkerStartData start_data_; MockServiceWorkerContextClient* mock_client_; MockServiceWorkerInstalledScriptsManager* mock_installed_scripts_manager_; - std::unique_ptr<WebEmbeddedWorker> worker_; + std::unique_ptr<WebEmbeddedWorkerImpl> worker_; }; } // namespace @@ -189,7 +206,7 @@ .WillOnce(::testing::Return(nullptr)); if (mock_installed_scripts_manager_) { EXPECT_CALL(*mock_installed_scripts_manager_, - IsScriptInstalled(start_data_.script_url)) + IsScriptInstalled(KURL(start_data_.script_url))) .Times(1) .WillOnce(::testing::Return(false)); } @@ -218,7 +235,7 @@ .WillOnce(::testing::Return(nullptr)); if (mock_installed_scripts_manager_) { EXPECT_CALL(*mock_installed_scripts_manager_, - IsScriptInstalled(start_data_.script_url)) + IsScriptInstalled(KURL(start_data_.script_url))) .Times(1) .WillOnce(::testing::Return(false)); } @@ -262,7 +279,7 @@ .WillOnce(::testing::Return(nullptr)); if (mock_installed_scripts_manager_) { EXPECT_CALL(*mock_installed_scripts_manager_, - IsScriptInstalled(start_data_.script_url)) + IsScriptInstalled(KURL(start_data_.script_url))) .Times(1) .WillOnce(::testing::Return(false)); } @@ -291,7 +308,7 @@ .WillOnce(::testing::Return(nullptr)); if (mock_installed_scripts_manager_) { EXPECT_CALL(*mock_installed_scripts_manager_, - IsScriptInstalled(start_data_.script_url)) + IsScriptInstalled(KURL(start_data_.script_url))) .Times(1) .WillOnce(::testing::Return(false)); } @@ -309,7 +326,7 @@ // This is called on the worker thread. if (mock_installed_scripts_manager_) { EXPECT_CALL(*mock_installed_scripts_manager_, - IsScriptInstalled(start_data_.script_url)) + IsScriptInstalled(KURL(start_data_.script_url))) .Times(1) .WillOnce(::testing::Return(false)); } @@ -339,7 +356,7 @@ .WillOnce(::testing::Return(nullptr)); if (mock_installed_scripts_manager_) { EXPECT_CALL(*mock_installed_scripts_manager_, - IsScriptInstalled(start_data_.script_url)) + IsScriptInstalled(KURL(start_data_.script_url))) .Times(1) .WillOnce(::testing::Return(false)); } @@ -362,7 +379,7 @@ // This is called on the worker thread. if (mock_installed_scripts_manager_) { EXPECT_CALL(*mock_installed_scripts_manager_, - IsScriptInstalled(start_data_.script_url)) + IsScriptInstalled(KURL(start_data_.script_url))) .Times(1) .WillOnce(::testing::Return(false)); }
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp index d8618b0..8ec231e 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletGlobalScopeTest.cpp
@@ -75,9 +75,7 @@ nullptr /* worker_clients */, document->AddressSpace(), OriginTrialContext::GetTokens(document).get(), nullptr /* worker_settings */, kV8CacheOptionsDefault), - WTF::nullopt, - std::make_unique<GlobalScopeInspectorCreationParams>( - WorkerInspectorProxy::PauseOnWorkerStart::kDontPause), + WTF::nullopt, WorkerInspectorProxy::PauseOnWorkerStart::kDontPause, ParentFrameTaskRunners::Create()); return thread; }
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioWorkletThreadTest.cpp b/third_party/WebKit/Source/modules/webaudio/AudioWorkletThreadTest.cpp index a8907e8..f424549 100644 --- a/third_party/WebKit/Source/modules/webaudio/AudioWorkletThreadTest.cpp +++ b/third_party/WebKit/Source/modules/webaudio/AudioWorkletThreadTest.cpp
@@ -59,9 +59,7 @@ nullptr /* worker_clients */, document->AddressSpace(), OriginTrialContext::GetTokens(document).get(), nullptr /* worker_settings */, kV8CacheOptionsDefault), - WTF::nullopt, - std::make_unique<GlobalScopeInspectorCreationParams>( - WorkerInspectorProxy::PauseOnWorkerStart::kDontPause), + WTF::nullopt, WorkerInspectorProxy::PauseOnWorkerStart::kDontPause, ParentFrameTaskRunners::Create()); return thread; }
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp index 742b3c2..1cf14af 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp
@@ -773,17 +773,14 @@ std::make_unique<AcceleratedImageBufferSurface>(size, ColorParams()); if (!surface->IsValid()) return nullptr; - std::unique_ptr<ImageBuffer> buffer = - ImageBuffer::Create(std::move(surface)); - if (!buffer->CopyRenderingResultsFromDrawingBuffer(GetDrawingBuffer(), - kBackBuffer)) { + if (!CopyRenderingResultsFromDrawingBuffer(surface.get(), kBackBuffer)) { // copyRenderingResultsFromDrawingBuffer is expected to always succeed // because we've explicitly created an Accelerated surface and have // already validated it. NOTREACHED(); return nullptr; } - return buffer->NewImageSnapshot(hint, reason); + return surface->NewImageSnapshot(hint, reason); } // If on a worker thread, create a copy from the drawing buffer and create @@ -1463,17 +1460,15 @@ canvas()->ClearCopiedImage(); marked_canvas_dirty_ = false; - if (!canvas()->GetOrCreateImageBuffer()) + if (!canvas()->TryCreateImageBuffer()) return false; ScopedTexture2DRestorer restorer(this); ScopedFramebufferRestorer fbo_restorer(this); GetDrawingBuffer()->ResolveAndBindForReadAndDraw(); - if (!canvas() - ->GetOrCreateImageBuffer() - ->CopyRenderingResultsFromDrawingBuffer(GetDrawingBuffer(), - source_buffer)) { + if (!CopyRenderingResultsFromDrawingBuffer(canvas()->WebGLBuffer(), + source_buffer)) { // Currently, copyRenderingResultsFromDrawingBuffer is expected to always // succeed because cases where canvas()-buffer() is not accelerated are // handle before reaching this point. If that assumption ever stops holding @@ -1485,6 +1480,29 @@ return true; } +bool WebGLRenderingContextBase::CopyRenderingResultsFromDrawingBuffer( + AcceleratedImageBufferSurface* webgl_buffer, + SourceDrawingBuffer source_buffer) const { + if (!drawing_buffer_) + return false; + std::unique_ptr<WebGraphicsContext3DProvider> provider = + Platform::Current()->CreateSharedOffscreenGraphicsContext3DProvider(); + if (!provider) + return false; + gpu::gles2::GLES2Interface* gl = provider->ContextGL(); + GLuint texture_id = webgl_buffer->GetBackingTextureHandleForOverwrite(); + if (!texture_id) + return false; + + // TODO(xlai): Flush should not be necessary if the synchronization in + // CopyToPlatformTexture is done correctly. See crbug.com/794706. + gl->Flush(); + + return drawing_buffer_->CopyToPlatformTexture( + gl, GL_TEXTURE_2D, texture_id, true, false, IntPoint(0, 0), + IntRect(IntPoint(0, 0), drawing_buffer_->Size()), source_buffer); +} + IntSize WebGLRenderingContextBase::DrawingBufferSize() const { if (isContextLost()) return IntSize(0, 0); @@ -4960,14 +4978,19 @@ GLint yoffset, const IntRect& source_sub_rectangle) { if (!canvas->Is3d()) { - ImageBuffer* buffer = canvas->GetOrCreateImageBuffer(); - if (buffer && - !buffer->CopyToPlatformTexture( - FunctionIDToSnapshotReason(function_id), ContextGL(), target, - target_texture, unpack_premultiply_alpha_, unpack_flip_y_, - IntPoint(xoffset, yoffset), source_sub_rectangle)) { - NOTREACHED(); + if (Extensions3DUtil::CanUseCopyTextureCHROMIUM(target) && + canvas->TryCreateImageBuffer()) { + scoped_refptr<StaticBitmapImage> image = + canvas->Canvas2DBuffer()->NewImageSnapshot( + kPreferAcceleration, FunctionIDToSnapshotReason(function_id)); + if (!!image && image->CopyImageToPlatformTexture( + ContextGL(), target, target_texture, + unpack_premultiply_alpha_, unpack_flip_y_, + IntPoint(xoffset, yoffset), source_sub_rectangle)) { + return; + } } + NOTREACHED(); } else { WebGLRenderingContextBase* gl = ToWebGLRenderingContextBase(canvas->RenderingContext()); @@ -5304,34 +5327,34 @@ if (use_copyTextureCHROMIUM) { // Try using an accelerated image buffer, this allows YUV conversion to be // done on the GPU. - std::unique_ptr<ImageBufferSurface> surface = + std::unique_ptr<AcceleratedImageBufferSurface> surface = WTF::WrapUnique(new AcceleratedImageBufferSurface( IntSize(video->videoWidth(), video->videoHeight()))); if (surface->IsValid()) { - std::unique_ptr<ImageBuffer> image_buffer( - ImageBuffer::Create(std::move(surface))); - if (image_buffer) { - // The video element paints an RGBA frame into our surface here. By - // using an AcceleratedImageBufferSurface, we enable the WebMediaPlayer - // implementation to do any necessary color space conversion on the GPU - // (though it may still do a CPU conversion and upload the results). - video->PaintCurrentFrame( - image_buffer->Canvas(), - IntRect(0, 0, video->videoWidth(), video->videoHeight()), nullptr, - already_uploaded_id, frame_metadata_ptr); + // The video element paints an RGBA frame into our surface here. By + // using an AcceleratedImageBufferSurface, we enable the WebMediaPlayer + // implementation to do any necessary color space conversion on the GPU + // (though it may still do a CPU conversion and upload the results). + video->PaintCurrentFrame( + surface->Canvas(), + IntRect(0, 0, video->videoWidth(), video->videoHeight()), nullptr, + already_uploaded_id, frame_metadata_ptr); - // This is a straight GPU-GPU copy, any necessary color space conversion - // was handled in the paintCurrentFrameInContext() call. + // This is a straight GPU-GPU copy, any necessary color space conversion + // was handled in the paintCurrentFrameInContext() call. - // Note that copyToPlatformTexture no longer allocates the destination - // texture. - TexImage2DBase(target, level, internalformat, video->videoWidth(), - video->videoHeight(), 0, format, type, nullptr); + // Note that copyToPlatformTexture no longer allocates the destination + // texture. + TexImage2DBase(target, level, internalformat, video->videoWidth(), + video->videoHeight(), 0, format, type, nullptr); - if (image_buffer->CopyToPlatformTexture( - FunctionIDToSnapshotReason(function_id), ContextGL(), target, - texture->Object(), unpack_premultiply_alpha_, unpack_flip_y_, - IntPoint(0, 0), + if (Extensions3DUtil::CanUseCopyTextureCHROMIUM(target)) { + scoped_refptr<StaticBitmapImage> image = surface->NewImageSnapshot( + kPreferAcceleration, FunctionIDToSnapshotReason(function_id)); + if (!!image && + image->CopyImageToPlatformTexture( + ContextGL(), target, texture->Object(), + unpack_premultiply_alpha_, unpack_flip_y_, IntPoint(0, 0), IntRect(0, 0, video->videoWidth(), video->videoHeight()))) { texture->UpdateLastUploadedFrame(frame_metadata); return;
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h index ac82de5..17593bd5 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h +++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h
@@ -1698,6 +1698,8 @@ const unsigned version_; bool IsPaintable() const final { return GetDrawingBuffer(); } + bool CopyRenderingResultsFromDrawingBuffer(AcceleratedImageBufferSurface*, + SourceDrawingBuffer) const; }; // TODO(fserb): remove this.
diff --git a/third_party/WebKit/Source/platform/BUILD.gn b/third_party/WebKit/Source/platform/BUILD.gn index 2071b75..c65774bf 100644 --- a/third_party/WebKit/Source/platform/BUILD.gn +++ b/third_party/WebKit/Source/platform/BUILD.gn
@@ -16,7 +16,10 @@ # Most targets in this file are private actions so use that as the default. visibility = [ ":*" ] -blink_platform_neon_files = [ "graphics/cpu/arm/WebGLImageConversionNEON.h" ] +blink_platform_neon_files = [ + "audio/cpu/arm/VectorMathNEON.h", + "graphics/cpu/arm/WebGLImageConversionNEON.h", +] blink_platform_msa_files = [ "graphics/cpu/mips/WebGLImageConversionMSA.h" ] @@ -470,10 +473,12 @@ "audio/VectorMath.h", "audio/VectorMathScalar.h", "audio/android/FFTFrameOpenMAXDLAndroid.cpp", + "audio/cpu/arm/VectorMathNEON.h", "audio/cpu/x86/VectorMathSSE.h", "audio/cpu/x86/VectorMathX86.h", "audio/ffmpeg/FFTFrameFFMPEG.cpp", "audio/mac/FFTFrameMac.cpp", + "audio/mac/VectorMathMac.h", "bindings/ActiveScriptWrappableBase.cpp", "bindings/ActiveScriptWrappableBase.h", "bindings/CallbackFunctionBase.cpp", @@ -630,7 +635,6 @@ "exported/WebScrollbarThemeGeometryNative.h", "exported/WebScrollbarThemePainter.cpp", "exported/WebSecurityOrigin.cpp", - "exported/WebServiceWorkerInstalledScriptsManager.cpp", "exported/WebServiceWorkerRequest.cpp", "exported/WebServiceWorkerResponse.cpp", "exported/WebServiceWorkerStreamHandle.cpp",
diff --git a/third_party/WebKit/Source/platform/WaitableEvent.cpp b/third_party/WebKit/Source/platform/WaitableEvent.cpp index c00f606..cd61b2f 100644 --- a/third_party/WebKit/Source/platform/WaitableEvent.cpp +++ b/third_party/WebKit/Source/platform/WaitableEvent.cpp
@@ -37,6 +37,10 @@ impl_->Signal(); } +bool WaitableEvent::IsSignaled() { + return impl_->IsSignaled(); +} + size_t WaitableEvent::WaitMultiple(const WTF::Vector<WaitableEvent*>& events) { std::vector<base::WaitableEvent*> base_events; for (size_t i = 0; i < events.size(); ++i)
diff --git a/third_party/WebKit/Source/platform/WaitableEvent.h b/third_party/WebKit/Source/platform/WaitableEvent.h index 106b0201..6fe0550 100644 --- a/third_party/WebKit/Source/platform/WaitableEvent.h +++ b/third_party/WebKit/Source/platform/WaitableEvent.h
@@ -70,6 +70,10 @@ // a waiting thread has been released. void Signal(); + // Returns true if the event is in the signaled state, else false. If this + // is not a manual reset event, then this test will cause a reset. + bool IsSignaled(); + // Waits on multiple events and returns the index of the object that // has been signaled. Any event objects given to this method must // not deleted while this wait is happening.
diff --git a/third_party/WebKit/Source/platform/audio/VectorMath.cpp b/third_party/WebKit/Source/platform/audio/VectorMath.cpp index 2ac31a1..2950177 100644 --- a/third_party/WebKit/Source/platform/audio/VectorMath.cpp +++ b/third_party/WebKit/Source/platform/audio/VectorMath.cpp
@@ -31,21 +31,15 @@ #include "platform/wtf/Assertions.h" #include "platform/wtf/CPU.h" -#if !defined(OS_MACOSX) -#if defined(ARCH_CPU_X86_FAMILY) +#if defined(OS_MACOSX) +#include "platform/audio/mac/VectorMathMac.h" +#elif WTF_CPU_ARM_NEON +#include "platform/audio/cpu/arm/VectorMathNEON.h" +#elif defined(ARCH_CPU_X86_FAMILY) #include "platform/audio/cpu/x86/VectorMathX86.h" #else #include "platform/audio/VectorMathScalar.h" #endif -#endif - -#if defined(OS_MACOSX) -#include <Accelerate/Accelerate.h> -#endif - -#if WTF_CPU_ARM_NEON -#include <arm_neon.h> -#endif #if HAVE_MIPS_MSA_INTRINSICS #include "platform/cpu/mips/CommonMacrosMSA.h" @@ -57,124 +51,12 @@ namespace VectorMath { -#if defined(OS_MACOSX) -// On the Mac we use the highly optimized versions in Accelerate.framework -// In 32-bit mode (__ppc__ or __i386__) <Accelerate/Accelerate.h> includes -// <vecLib/vDSP_translate.h> which defines macros of the same name as -// our namespaced function names, so we must handle this case differently. Other -// architectures (64bit, ARM, etc.) do not include this header file. - -void Vsmul(const float* source_p, - int source_stride, - const float* scale, - float* dest_p, - int dest_stride, - size_t frames_to_process) { -#if defined(ARCH_CPU_X86) - ::vsmul(source_p, source_stride, scale, dest_p, dest_stride, - frames_to_process); -#else - vDSP_vsmul(source_p, source_stride, scale, dest_p, dest_stride, - frames_to_process); -#endif -} - -void Vadd(const float* source1p, - int source_stride1, - const float* source2p, - int source_stride2, - float* dest_p, - int dest_stride, - size_t frames_to_process) { -#if defined(ARCH_CPU_X86) - ::vadd(source1p, source_stride1, source2p, source_stride2, dest_p, - dest_stride, frames_to_process); -#else - vDSP_vadd(source1p, source_stride1, source2p, source_stride2, dest_p, - dest_stride, frames_to_process); -#endif -} - -void Vmul(const float* source1p, - int source_stride1, - const float* source2p, - int source_stride2, - float* dest_p, - int dest_stride, - size_t frames_to_process) { -#if defined(ARCH_CPU_X86) - ::vmul(source1p, source_stride1, source2p, source_stride2, dest_p, - dest_stride, frames_to_process); -#else - vDSP_vmul(source1p, source_stride1, source2p, source_stride2, dest_p, - dest_stride, frames_to_process); -#endif -} - -void Zvmul(const float* real1p, - const float* imag1p, - const float* real2p, - const float* imag2p, - float* real_dest_p, - float* imag_dest_p, - size_t frames_to_process) { - DSPSplitComplex sc1; - DSPSplitComplex sc2; - DSPSplitComplex dest; - sc1.realp = const_cast<float*>(real1p); - sc1.imagp = const_cast<float*>(imag1p); - sc2.realp = const_cast<float*>(real2p); - sc2.imagp = const_cast<float*>(imag2p); - dest.realp = real_dest_p; - dest.imagp = imag_dest_p; -#if defined(ARCH_CPU_X86) - ::zvmul(&sc1, 1, &sc2, 1, &dest, 1, frames_to_process, 1); -#else - vDSP_zvmul(&sc1, 1, &sc2, 1, &dest, 1, frames_to_process, 1); -#endif -} - -void Vsma(const float* source_p, - int source_stride, - const float* scale, - float* dest_p, - int dest_stride, - size_t frames_to_process) { - vDSP_vsma(source_p, source_stride, scale, dest_p, dest_stride, dest_p, - dest_stride, frames_to_process); -} - -void Vmaxmgv(const float* source_p, - int source_stride, - float* max_p, - size_t frames_to_process) { - vDSP_maxmgv(source_p, source_stride, max_p, frames_to_process); -} - -void Vsvesq(const float* source_p, - int source_stride, - float* sum_p, - size_t frames_to_process) { - vDSP_svesq(const_cast<float*>(source_p), source_stride, sum_p, - frames_to_process); -} - -void Vclip(const float* source_p, - int source_stride, - const float* low_threshold_p, - const float* high_threshold_p, - float* dest_p, - int dest_stride, - size_t frames_to_process) { - vDSP_vclip(const_cast<float*>(source_p), source_stride, - const_cast<float*>(low_threshold_p), - const_cast<float*>(high_threshold_p), dest_p, dest_stride, - frames_to_process); -} -#else - namespace { -#if defined(ARCH_CPU_X86_FAMILY) +#if defined(OS_MACOSX) +namespace Impl = Mac; +#elif WTF_CPU_ARM_NEON +namespace Impl = NEON; +#elif defined(ARCH_CPU_X86_FAMILY) namespace Impl = X86; #else namespace Impl = Scalar; @@ -187,28 +69,9 @@ float* dest_p, int dest_stride, size_t frames_to_process) { -#if HAVE_MIPS_MSA_INTRINSICS || WTF_CPU_ARM_NEON +#if HAVE_MIPS_MSA_INTRINSICS int n = frames_to_process; -#if WTF_CPU_ARM_NEON - if ((source_stride == 1) && (dest_stride == 1)) { - int tail_frames = n % 4; - const float* end_p = dest_p + n - tail_frames; - - float32x4_t k = vdupq_n_f32(*scale); - while (dest_p < end_p) { - float32x4_t source = vld1q_f32(source_p); - float32x4_t dest = vld1q_f32(dest_p); - - dest = vmlaq_f32(dest, source, k); - vst1q_f32(dest_p, dest); - - source_p += 4; - dest_p += 4; - } - n = tail_frames; - } -#elif HAVE_MIPS_MSA_INTRINSICS if ((source_stride == 1) && (dest_stride == 1)) { float* destPCopy = dest_p; v4f32 vScale; @@ -229,7 +92,6 @@ ST_SP8(vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7, dest_p, 4); } } -#endif frames_to_process = n; #endif @@ -244,25 +106,9 @@ float* dest_p, int dest_stride, size_t frames_to_process) { -#if HAVE_MIPS_MSA_INTRINSICS || WTF_CPU_ARM_NEON +#if HAVE_MIPS_MSA_INTRINSICS int n = frames_to_process; -#if WTF_CPU_ARM_NEON - if ((source_stride == 1) && (dest_stride == 1)) { - float k = *scale; - int tail_frames = n % 4; - const float* end_p = dest_p + n - tail_frames; - - while (dest_p < end_p) { - float32x4_t source = vld1q_f32(source_p); - vst1q_f32(dest_p, vmulq_n_f32(source, k)); - - source_p += 4; - dest_p += 4; - } - n = tail_frames; - } -#elif HAVE_MIPS_MSA_INTRINSICS if ((source_stride == 1) && (dest_stride == 1)) { v4f32 vScale; v4f32 vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, vSrc7; @@ -280,7 +126,6 @@ ST_SP8(vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7, dest_p, 4); } } -#endif frames_to_process = n; #endif @@ -296,26 +141,9 @@ float* dest_p, int dest_stride, size_t frames_to_process) { -#if HAVE_MIPS_MSA_INTRINSICS || WTF_CPU_ARM_NEON +#if HAVE_MIPS_MSA_INTRINSICS int n = frames_to_process; -#if WTF_CPU_ARM_NEON - if ((source_stride1 == 1) && (source_stride2 == 1) && (dest_stride == 1)) { - int tail_frames = n % 4; - const float* end_p = dest_p + n - tail_frames; - - while (dest_p < end_p) { - float32x4_t source1 = vld1q_f32(source1p); - float32x4_t source2 = vld1q_f32(source2p); - vst1q_f32(dest_p, vaddq_f32(source1, source2)); - - source1p += 4; - source2p += 4; - dest_p += 4; - } - n = tail_frames; - } -#elif HAVE_MIPS_MSA_INTRINSICS if ((source_stride1 == 1) && (source_stride2 == 1) && (dest_stride == 1)) { v4f32 vSrc1P0, vSrc1P1, vSrc1P2, vSrc1P3, vSrc1P4, vSrc1P5, vSrc1P6, vSrc1P7; @@ -335,7 +163,6 @@ ST_SP8(vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7, dest_p, 4); } } -#endif frames_to_process = n; #endif @@ -351,26 +178,9 @@ float* dest_p, int dest_stride, size_t frames_to_process) { -#if HAVE_MIPS_MSA_INTRINSICS || WTF_CPU_ARM_NEON +#if HAVE_MIPS_MSA_INTRINSICS int n = frames_to_process; -#if WTF_CPU_ARM_NEON - if ((source_stride1 == 1) && (source_stride2 == 1) && (dest_stride == 1)) { - int tail_frames = n % 4; - const float* end_p = dest_p + n - tail_frames; - - while (dest_p < end_p) { - float32x4_t source1 = vld1q_f32(source1p); - float32x4_t source2 = vld1q_f32(source2p); - vst1q_f32(dest_p, vmulq_f32(source1, source2)); - - source1p += 4; - source2p += 4; - dest_p += 4; - } - n = tail_frames; - } -#elif HAVE_MIPS_MSA_INTRINSICS if ((source_stride1 == 1) && (source_stride2 == 1) && (dest_stride == 1)) { v4f32 vSrc1P0, vSrc1P1, vSrc1P2, vSrc1P3, vSrc1P4, vSrc1P5, vSrc1P6, vSrc1P7; @@ -390,7 +200,6 @@ ST_SP8(vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7, dest_p, 4); } } -#endif frames_to_process = n; #endif @@ -406,28 +215,8 @@ float* real_dest_p, float* imag_dest_p, size_t frames_to_process) { - unsigned i = 0; - -#if WTF_CPU_ARM_NEON - unsigned end_size = frames_to_process - frames_to_process % 4; - while (i < end_size) { - float32x4_t real1 = vld1q_f32(real1p + i); - float32x4_t real2 = vld1q_f32(real2p + i); - float32x4_t imag1 = vld1q_f32(imag1p + i); - float32x4_t imag2 = vld1q_f32(imag2p + i); - - float32x4_t real_result = vmlsq_f32(vmulq_f32(real1, real2), imag1, imag2); - float32x4_t imag_result = vmlaq_f32(vmulq_f32(real1, imag2), imag1, real2); - - vst1q_f32(real_dest_p + i, real_result); - vst1q_f32(imag_dest_p + i, imag_result); - - i += 4; - } -#endif - - Impl::Zvmul(real1p + i, imag1p + i, real2p + i, imag2p + i, real_dest_p + i, - imag_dest_p + i, frames_to_process - i); + Impl::Zvmul(real1p, imag1p, real2p, imag2p, real_dest_p, imag_dest_p, + frames_to_process); } void Vsvesq(const float* source_p, @@ -436,32 +225,6 @@ size_t frames_to_process) { float sum = 0; -#if WTF_CPU_ARM_NEON - int n = frames_to_process; - - if (source_stride == 1) { - int tail_frames = n % 4; - const float* end_p = source_p + n - tail_frames; - - float32x4_t four_sum = vdupq_n_f32(0); - while (source_p < end_p) { - float32x4_t source = vld1q_f32(source_p); - four_sum = vmlaq_f32(four_sum, source, source); - source_p += 4; - } - float32x2_t two_sum = - vadd_f32(vget_low_f32(four_sum), vget_high_f32(four_sum)); - - float group_sum[2]; - vst1_f32(group_sum, two_sum); - sum += group_sum[0] + group_sum[1]; - - n = tail_frames; - } - - frames_to_process = n; -#endif - Impl::Vsvesq(source_p, source_stride, &sum, frames_to_process); DCHECK(sum_p); @@ -474,30 +237,9 @@ size_t frames_to_process) { float max = 0; -#if HAVE_MIPS_MSA_INTRINSICS || WTF_CPU_ARM_NEON +#if HAVE_MIPS_MSA_INTRINSICS int n = frames_to_process; -#if WTF_CPU_ARM_NEON - if (source_stride == 1) { - int tail_frames = n % 4; - const float* end_p = source_p + n - tail_frames; - - float32x4_t four_max = vdupq_n_f32(0); - while (source_p < end_p) { - float32x4_t source = vld1q_f32(source_p); - four_max = vmaxq_f32(four_max, vabsq_f32(source)); - source_p += 4; - } - float32x2_t two_max = - vmax_f32(vget_low_f32(four_max), vget_high_f32(four_max)); - - float group_max[2]; - vst1_f32(group_max, two_max); - max = std::max(group_max[0], group_max[1]); - - n = tail_frames; - } -#elif HAVE_MIPS_MSA_INTRINSICS if (source_stride == 1) { v4f32 vMax = { 0, @@ -519,7 +261,6 @@ max = std::max(max, vMax[2]); max = std::max(max, vMax[3]); } -#endif frames_to_process = n; #endif @@ -549,25 +290,9 @@ DCHECK_LE(low_threshold, high_threshold); #endif -#if HAVE_MIPS_MSA_INTRINSICS || WTF_CPU_ARM_NEON +#if HAVE_MIPS_MSA_INTRINSICS int n = frames_to_process; -#if WTF_CPU_ARM_NEON - if ((source_stride == 1) && (dest_stride == 1)) { - int tail_frames = n % 4; - const float* end_p = dest_p + n - tail_frames; - - float32x4_t low = vdupq_n_f32(low_threshold); - float32x4_t high = vdupq_n_f32(high_threshold); - while (dest_p < end_p) { - float32x4_t source = vld1q_f32(source_p); - vst1q_f32(dest_p, vmaxq_f32(vminq_f32(source, high), low)); - source_p += 4; - dest_p += 4; - } - n = tail_frames; - } -#elif HAVE_MIPS_MSA_INTRINSICS if ((source_stride == 1) && (dest_stride == 1)) { v4f32 vSrc0, vSrc1, vSrc2, vSrc3, vSrc4, vSrc5, vSrc6, vSrc7; v4f32 vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7; @@ -589,7 +314,6 @@ ST_SP8(vDst0, vDst1, vDst2, vDst3, vDst4, vDst5, vDst6, vDst7, dest_p, 4); } } -#endif frames_to_process = n; #endif @@ -598,8 +322,6 @@ dest_stride, frames_to_process); } -#endif // defined(OS_MACOSX) - } // namespace VectorMath } // namespace blink
diff --git a/third_party/WebKit/Source/platform/audio/cpu/arm/VectorMathNEON.h b/third_party/WebKit/Source/platform/audio/cpu/arm/VectorMathNEON.h new file mode 100644 index 0000000..3a012bb --- /dev/null +++ b/third_party/WebKit/Source/platform/audio/cpu/arm/VectorMathNEON.h
@@ -0,0 +1,250 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef VectorMathNEON_h +#define VectorMathNEON_h + +#include <arm_neon.h> + +#include <algorithm> + +#include "platform/audio/VectorMathScalar.h" + +namespace blink { +namespace VectorMath { +namespace NEON { + +static ALWAYS_INLINE void Vadd(const float* source1p, + int source_stride1, + const float* source2p, + int source_stride2, + float* dest_p, + int dest_stride, + size_t frames_to_process) { + int n = frames_to_process; + + if (source_stride1 == 1 && source_stride2 == 1 && dest_stride == 1) { + int tail_frames = n % 4; + const float* end_p = dest_p + n - tail_frames; + + while (dest_p < end_p) { + float32x4_t source1 = vld1q_f32(source1p); + float32x4_t source2 = vld1q_f32(source2p); + vst1q_f32(dest_p, vaddq_f32(source1, source2)); + + source1p += 4; + source2p += 4; + dest_p += 4; + } + n = tail_frames; + } + + Scalar::Vadd(source1p, source_stride1, source2p, source_stride2, dest_p, + dest_stride, n); +} + +static ALWAYS_INLINE void Vclip(const float* source_p, + int source_stride, + const float* low_threshold_p, + const float* high_threshold_p, + float* dest_p, + int dest_stride, + size_t frames_to_process) { + int n = frames_to_process; + + if (source_stride == 1 && dest_stride == 1) { + int tail_frames = n % 4; + const float* end_p = dest_p + n - tail_frames; + + float32x4_t low = vdupq_n_f32(*low_threshold_p); + float32x4_t high = vdupq_n_f32(*high_threshold_p); + while (dest_p < end_p) { + float32x4_t source = vld1q_f32(source_p); + vst1q_f32(dest_p, vmaxq_f32(vminq_f32(source, high), low)); + source_p += 4; + dest_p += 4; + } + n = tail_frames; + } + + Scalar::Vclip(source_p, source_stride, low_threshold_p, high_threshold_p, + dest_p, dest_stride, n); +} + +static ALWAYS_INLINE void Vmaxmgv(const float* source_p, + int source_stride, + float* max_p, + size_t frames_to_process) { + int n = frames_to_process; + + if (source_stride == 1) { + int tail_frames = n % 4; + const float* end_p = source_p + n - tail_frames; + + float32x4_t four_max = vdupq_n_f32(*max_p); + while (source_p < end_p) { + float32x4_t source = vld1q_f32(source_p); + four_max = vmaxq_f32(four_max, vabsq_f32(source)); + source_p += 4; + } + float32x2_t two_max = + vmax_f32(vget_low_f32(four_max), vget_high_f32(four_max)); + + float group_max[2]; + vst1_f32(group_max, two_max); + *max_p = std::max(group_max[0], group_max[1]); + + n = tail_frames; + } + + Scalar::Vmaxmgv(source_p, source_stride, max_p, n); +} + +static ALWAYS_INLINE void Vmul(const float* source1p, + int source_stride1, + const float* source2p, + int source_stride2, + float* dest_p, + int dest_stride, + size_t frames_to_process) { + int n = frames_to_process; + + if (source_stride1 == 1 && source_stride2 == 1 && dest_stride == 1) { + int tail_frames = n % 4; + const float* end_p = dest_p + n - tail_frames; + + while (dest_p < end_p) { + float32x4_t source1 = vld1q_f32(source1p); + float32x4_t source2 = vld1q_f32(source2p); + vst1q_f32(dest_p, vmulq_f32(source1, source2)); + + source1p += 4; + source2p += 4; + dest_p += 4; + } + n = tail_frames; + } + + Scalar::Vmul(source1p, source_stride1, source2p, source_stride2, dest_p, + dest_stride, n); +} + +static ALWAYS_INLINE void Vsma(const float* source_p, + int source_stride, + const float* scale, + float* dest_p, + int dest_stride, + size_t frames_to_process) { + int n = frames_to_process; + + if (source_stride == 1 && dest_stride == 1) { + int tail_frames = n % 4; + const float* end_p = dest_p + n - tail_frames; + + float32x4_t k = vdupq_n_f32(*scale); + while (dest_p < end_p) { + float32x4_t source = vld1q_f32(source_p); + float32x4_t dest = vld1q_f32(dest_p); + + dest = vmlaq_f32(dest, source, k); + vst1q_f32(dest_p, dest); + + source_p += 4; + dest_p += 4; + } + n = tail_frames; + } + + Scalar::Vsma(source_p, source_stride, scale, dest_p, dest_stride, n); +} + +static ALWAYS_INLINE void Vsmul(const float* source_p, + int source_stride, + const float* scale, + float* dest_p, + int dest_stride, + size_t frames_to_process) { + int n = frames_to_process; + + if (source_stride == 1 && dest_stride == 1) { + float k = *scale; + int tail_frames = n % 4; + const float* end_p = dest_p + n - tail_frames; + + while (dest_p < end_p) { + float32x4_t source = vld1q_f32(source_p); + vst1q_f32(dest_p, vmulq_n_f32(source, k)); + + source_p += 4; + dest_p += 4; + } + n = tail_frames; + } + + Scalar::Vsmul(source_p, source_stride, scale, dest_p, dest_stride, n); +} + +static ALWAYS_INLINE void Vsvesq(const float* source_p, + int source_stride, + float* sum_p, + size_t frames_to_process) { + int n = frames_to_process; + + if (source_stride == 1) { + int tail_frames = n % 4; + const float* end_p = source_p + n - tail_frames; + + float32x4_t four_sum = vdupq_n_f32(0); + while (source_p < end_p) { + float32x4_t source = vld1q_f32(source_p); + four_sum = vmlaq_f32(four_sum, source, source); + source_p += 4; + } + float32x2_t two_sum = + vadd_f32(vget_low_f32(four_sum), vget_high_f32(four_sum)); + + float group_sum[2]; + vst1_f32(group_sum, two_sum); + *sum_p += group_sum[0] + group_sum[1]; + + n = tail_frames; + } + + Scalar::Vsvesq(source_p, source_stride, sum_p, n); +} + +static ALWAYS_INLINE void Zvmul(const float* real1p, + const float* imag1p, + const float* real2p, + const float* imag2p, + float* real_dest_p, + float* imag_dest_p, + size_t frames_to_process) { + unsigned i = 0; + + unsigned end_size = frames_to_process - frames_to_process % 4; + while (i < end_size) { + float32x4_t real1 = vld1q_f32(real1p + i); + float32x4_t real2 = vld1q_f32(real2p + i); + float32x4_t imag1 = vld1q_f32(imag1p + i); + float32x4_t imag2 = vld1q_f32(imag2p + i); + + float32x4_t real_result = vmlsq_f32(vmulq_f32(real1, real2), imag1, imag2); + float32x4_t imag_result = vmlaq_f32(vmulq_f32(real1, imag2), imag1, real2); + + vst1q_f32(real_dest_p + i, real_result); + vst1q_f32(imag_dest_p + i, imag_result); + + i += 4; + } + + Scalar::Zvmul(real1p + i, imag1p + i, real2p + i, imag2p + i, real_dest_p + i, + imag_dest_p + i, frames_to_process - i); +} + +} // namespace NEON +} // namespace VectorMath +} // namespace blink + +#endif // VectorMathNEON_h
diff --git a/third_party/WebKit/Source/platform/audio/mac/VectorMathMac.h b/third_party/WebKit/Source/platform/audio/mac/VectorMathMac.h new file mode 100644 index 0000000..d5b59a2 --- /dev/null +++ b/third_party/WebKit/Source/platform/audio/mac/VectorMathMac.h
@@ -0,0 +1,134 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef VectorMathMac_h +#define VectorMathMac_h + +#include <Accelerate/Accelerate.h> + +#include "build/build_config.h" + +namespace blink { +namespace VectorMath { +namespace Mac { + +// On the Mac we use the highly optimized versions in Accelerate.framework +// In 32-bit mode (__ppc__ or __i386__) <Accelerate/Accelerate.h> includes +// <vecLib/vDSP_translate.h> which defines macros of the same name as +// our namespaced function names, so we must handle this case differently. Other +// architectures (64bit, ARM, etc.) do not include this header file. + +static ALWAYS_INLINE void Vadd(const float* source1p, + int source_stride1, + const float* source2p, + int source_stride2, + float* dest_p, + int dest_stride, + size_t frames_to_process) { +#if defined(ARCH_CPU_X86) + ::vadd(source1p, source_stride1, source2p, source_stride2, dest_p, + dest_stride, frames_to_process); +#else + vDSP_vadd(source1p, source_stride1, source2p, source_stride2, dest_p, + dest_stride, frames_to_process); +#endif +} + +static ALWAYS_INLINE void Vclip(const float* source_p, + int source_stride, + const float* low_threshold_p, + const float* high_threshold_p, + float* dest_p, + int dest_stride, + size_t frames_to_process) { + vDSP_vclip(const_cast<float*>(source_p), source_stride, + const_cast<float*>(low_threshold_p), + const_cast<float*>(high_threshold_p), dest_p, dest_stride, + frames_to_process); +} + +static ALWAYS_INLINE void Vmaxmgv(const float* source_p, + int source_stride, + float* max_p, + size_t frames_to_process) { + vDSP_maxmgv(source_p, source_stride, max_p, frames_to_process); +} + +static ALWAYS_INLINE void Vmul(const float* source1p, + int source_stride1, + const float* source2p, + int source_stride2, + float* dest_p, + int dest_stride, + size_t frames_to_process) { +#if defined(ARCH_CPU_X86) + ::vmul(source1p, source_stride1, source2p, source_stride2, dest_p, + dest_stride, frames_to_process); +#else + vDSP_vmul(source1p, source_stride1, source2p, source_stride2, dest_p, + dest_stride, frames_to_process); +#endif +} + +static ALWAYS_INLINE void Vsma(const float* source_p, + int source_stride, + const float* scale, + float* dest_p, + int dest_stride, + size_t frames_to_process) { + vDSP_vsma(source_p, source_stride, scale, dest_p, dest_stride, dest_p, + dest_stride, frames_to_process); +} + +static ALWAYS_INLINE void Vsmul(const float* source_p, + int source_stride, + const float* scale, + float* dest_p, + int dest_stride, + size_t frames_to_process) { +#if defined(ARCH_CPU_X86) + ::vsmul(source_p, source_stride, scale, dest_p, dest_stride, + frames_to_process); +#else + vDSP_vsmul(source_p, source_stride, scale, dest_p, dest_stride, + frames_to_process); +#endif +} + +static ALWAYS_INLINE void Vsvesq(const float* source_p, + int source_stride, + float* sum_p, + size_t frames_to_process) { + vDSP_svesq(const_cast<float*>(source_p), source_stride, sum_p, + frames_to_process); +} + +static ALWAYS_INLINE void Zvmul(const float* real1p, + const float* imag1p, + const float* real2p, + const float* imag2p, + float* real_dest_p, + float* imag_dest_p, + size_t frames_to_process) { + DSPSplitComplex sc1; + DSPSplitComplex sc2; + DSPSplitComplex dest; + sc1.realp = const_cast<float*>(real1p); + sc1.imagp = const_cast<float*>(imag1p); + sc2.realp = const_cast<float*>(real2p); + sc2.imagp = const_cast<float*>(imag2p); + dest.realp = real_dest_p; + dest.imagp = imag_dest_p; +#if defined(ARCH_CPU_X86) + ::zvmul(&sc1, 1, &sc2, 1, &dest, 1, frames_to_process, 1); +#else + vDSP_zvmul(&sc1, 1, &sc2, 1, &dest, 1, frames_to_process, 1); +#endif +} + +} // namespace Mac +} // namespace VectorMath +} // namespace blink + +#endif // VectorMathMac_h
diff --git a/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.cpp b/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.cpp index aa3070dc..6e4bf3f 100644 --- a/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.cpp +++ b/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.cpp
@@ -52,7 +52,7 @@ bool WebActiveGestureAnimation::Animate(double time) { // All WebGestureCurves assume zero-based time, so we subtract // the animation start time before passing to the curve. - return curve_->Apply(time - start_time_, target_); + return curve_->AdvanceAndApplyToTarget(time - start_time_, target_); } } // namespace blink
diff --git a/third_party/WebKit/Source/platform/exported/WebServiceWorkerInstalledScriptsManager.cpp b/third_party/WebKit/Source/platform/exported/WebServiceWorkerInstalledScriptsManager.cpp deleted file mode 100644 index 3ba7905..0000000 --- a/third_party/WebKit/Source/platform/exported/WebServiceWorkerInstalledScriptsManager.cpp +++ /dev/null
@@ -1,51 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h" - -#include <memory> - -namespace blink { - -// static -std::unique_ptr<WebServiceWorkerInstalledScriptsManager::RawScriptData> -WebServiceWorkerInstalledScriptsManager::RawScriptData::Create( - WebString encoding, - WebVector<BytesChunk> script_text, - WebVector<BytesChunk> meta_data) { - return WTF::WrapUnique( - new RawScriptData(std::move(encoding), std::move(script_text), - std::move(meta_data), true /* is_valid */)); -} - -// static -std::unique_ptr<WebServiceWorkerInstalledScriptsManager::RawScriptData> -WebServiceWorkerInstalledScriptsManager::RawScriptData:: - CreateInvalidInstance() { - return WTF::WrapUnique( - new RawScriptData(WebString() /* encoding */, WebVector<BytesChunk>(), - WebVector<BytesChunk>(), false /* is_valid */)); -} - -WebServiceWorkerInstalledScriptsManager::RawScriptData::RawScriptData( - WebString encoding, - WebVector<BytesChunk> script_text, - WebVector<BytesChunk> meta_data, - bool is_valid) - : is_valid_(is_valid), - encoding_(std::move(encoding)), - script_text_(std::move(script_text)), - meta_data_(std::move(meta_data)), - headers_(std::make_unique<CrossThreadHTTPHeaderMapData>()) {} - -WebServiceWorkerInstalledScriptsManager::RawScriptData::~RawScriptData() = - default; - -void WebServiceWorkerInstalledScriptsManager::RawScriptData::AddHeader( - const WebString& key, - const WebString& value) { - headers_->emplace_back(key, value); -} - -} // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp index 3c1c7db..53d6a19 100644 --- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp +++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp
@@ -78,12 +78,14 @@ software_rendering_while_hidden_(false), acceleration_mode_(acceleration_mode), color_params_(color_params), + snapshot_state_(kInitialSnapshotState), resource_host_(nullptr) { // Used by browser tests to detect the use of a Canvas2DLayerBridge. TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation", TRACE_EVENT_SCOPE_GLOBAL); StartRecording(); Clear(); + DidDraw(FloatRect(FloatPoint(0, 0), FloatSize(Size()))); } Canvas2DLayerBridge::~Canvas2DLayerBridge() { @@ -672,6 +674,8 @@ } void Canvas2DLayerBridge::DidDraw(const FloatRect& rect) { + if (snapshot_state_ == kDidAcquireSnapshot) + snapshot_state_ = kDrawnToAfterSnapshot; if (is_deferral_enabled_) { have_recorded_draw_commands_ = true; IntRect pixel_bounds = EnclosingIntRect(rect); @@ -730,6 +734,8 @@ scoped_refptr<StaticBitmapImage> Canvas2DLayerBridge::NewImageSnapshot( AccelerationHint hint, SnapshotReason) { + if (snapshot_state_ == kInitialSnapshotState) + snapshot_state_ = kDidAcquireSnapshot; if (IsHibernating()) return StaticBitmapImage::Create(hibernation_image_); if (!IsValid())
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h index f4325cb4..ada3c61 100644 --- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h +++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.h
@@ -89,20 +89,21 @@ std::unique_ptr<viz::SingleReleaseCallback>* out_release_callback) override; + void FinalizeFrame(); + void SetIsHidden(bool); + void DidDraw(const FloatRect&); + void DoPaintInvalidation(const FloatRect& dirty_rect); + WebLayer* Layer(); + bool Restore(); + virtual void WillOverwriteCanvas(); // virtual for unit testing + void DisableDeferral(DisableDeferralReason); + void SetFilterQuality(SkFilterQuality); + // ImageBufferSurface implementation - void FinalizeFrame() override; - void DoPaintInvalidation(const FloatRect& dirty_rect) override; - void WillOverwriteCanvas() override; PaintCanvas* Canvas() override; - void DisableDeferral(DisableDeferralReason) override; bool IsValid() const override; - bool Restore() override; - WebLayer* Layer() override; bool IsAccelerated() const override; - void SetFilterQuality(SkFilterQuality) override; - void SetIsHidden(bool) override; void SetImageBuffer(ImageBuffer*) override; - void DidDraw(const FloatRect&) override; bool WritePixels(const SkImageInfo&, const void* pixels, size_t row_bytes, @@ -124,6 +125,9 @@ scoped_refptr<StaticBitmapImage> NewImageSnapshot(AccelerationHint, SnapshotReason); + bool WasDrawnToAfterSnapshot() const { + return snapshot_state_ == kDrawnToAfterSnapshot; + } // The values of the enum entries must not change because they are used for // usage metrics histograms. New values can be added to the end. @@ -197,6 +201,13 @@ CanvasColorParams color_params_; CheckedNumeric<int> recording_pixel_count_; + enum SnapshotState { + kInitialSnapshotState, + kDidAcquireSnapshot, + kDrawnToAfterSnapshot, + }; + mutable SnapshotState snapshot_state_; + CanvasResourceHost* resource_host_; };
diff --git a/third_party/WebKit/Source/platform/graphics/CanvasResource.cpp b/third_party/WebKit/Source/platform/graphics/CanvasResource.cpp index fabae61..98e1d9e 100644 --- a/third_party/WebKit/Source/platform/graphics/CanvasResource.cpp +++ b/third_party/WebKit/Source/platform/graphics/CanvasResource.cpp
@@ -272,9 +272,7 @@ if (gpu_mailbox_.IsZero() && gl) { gl->GenMailboxCHROMIUM(gpu_mailbox_.name); gl->ProduceTextureDirectCHROMIUM(texture_id_, gpu_mailbox_.name); - const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM(); - gl->ShallowFlushCHROMIUM(); - gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token_.GetData()); + gl->GenUnverifiedSyncTokenCHROMIUM(sync_token_.GetData()); } return gpu_mailbox_; }
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp index 1efb6db..3b84c939 100644 --- a/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp +++ b/third_party/WebKit/Source/platform/graphics/ImageBuffer.cpp
@@ -33,36 +33,21 @@ #include "platform/graphics/ImageBuffer.h" #include <memory> -#include "gpu/command_buffer/client/gles2_interface.h" -#include "gpu/command_buffer/common/mailbox.h" -#include "gpu/command_buffer/common/sync_token.h" -#include "platform/geometry/IntRect.h" -#include "platform/graphics/CanvasHeuristicParameters.h" -#include "platform/graphics/GraphicsContext.h" #include "platform/graphics/StaticBitmapImage.h" #include "platform/graphics/UnacceleratedImageBufferSurface.h" #include "platform/graphics/gpu/DrawingBuffer.h" -#include "platform/graphics/gpu/Extensions3DUtil.h" #include "platform/graphics/paint/PaintImage.h" -#include "platform/graphics/paint/PaintRecord.h" -#include "platform/graphics/skia/SkiaUtils.h" #include "platform/image-encoders/ImageEncoder.h" #include "platform/network/mime/MIMETypeRegistry.h" -#include "platform/runtime_enabled_features.h" -#include "platform/wtf/MathExtras.h" #include "platform/wtf/PtrUtil.h" #include "platform/wtf/Vector.h" #include "platform/wtf/text/Base64.h" #include "platform/wtf/text/WTFString.h" #include "public/platform/Platform.h" #include "public/platform/WebGraphicsContext3DProvider.h" -#include "skia/ext/texture_handle.h" #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/core/SkSwizzle.h" #include "third_party/skia/include/encode/SkJpegEncoder.h" -#include "third_party/skia/include/gpu/GrContext.h" -#include "third_party/skia/include/gpu/gl/GrGLTypes.h" -#include "v8/include/v8.h" namespace blink { @@ -88,7 +73,6 @@ ImageBuffer::ImageBuffer(std::unique_ptr<ImageBufferSurface> surface) : weak_ptr_factory_(this), - snapshot_state_(kInitialSnapshotState), surface_(std::move(surface)) { surface_->SetImageBuffer(this); } @@ -97,248 +81,28 @@ surface_->SetImageBuffer(nullptr); } -bool ImageBuffer::CanCreateImageBuffer(const IntSize& size) { - if (size.IsEmpty()) - return false; - CheckedNumeric<int> area = size.Width(); - area *= size.Height(); - if (!area.IsValid() || area.ValueOrDie() > kMaxCanvasArea) - return false; - if (size.Width() > kMaxSkiaDim || size.Height() > kMaxSkiaDim) - return false; - return true; -} - PaintCanvas* ImageBuffer::Canvas() const { return surface_->Canvas(); } -void ImageBuffer::DisableDeferral(DisableDeferralReason reason) const { - return surface_->DisableDeferral(reason); -} - bool ImageBuffer::IsSurfaceValid() const { return surface_->IsValid(); } -void ImageBuffer::FinalizeFrame() { - surface_->FinalizeFrame(); -} - -void ImageBuffer::DoPaintInvalidation(const FloatRect& dirty_rect) { - surface_->DoPaintInvalidation(dirty_rect); -} - -bool ImageBuffer::RestoreSurface() const { - return surface_->IsValid() || surface_->Restore(); -} - scoped_refptr<StaticBitmapImage> ImageBuffer::NewImageSnapshot( AccelerationHint hint, SnapshotReason reason) const { - if (snapshot_state_ == kInitialSnapshotState) - snapshot_state_ = kDidAcquireSnapshot; if (!IsSurfaceValid()) return nullptr; return surface_->NewImageSnapshot(hint, reason); } -void ImageBuffer::DidDraw(const FloatRect& rect) const { - if (snapshot_state_ == kDidAcquireSnapshot) - snapshot_state_ = kDrawnToAfterSnapshot; - surface_->DidDraw(rect); -} - -WebLayer* ImageBuffer::PlatformLayer() const { - return surface_->Layer(); -} - -bool ImageBuffer::CopyToPlatformTexture(SnapshotReason reason, - gpu::gles2::GLES2Interface* gl, - GLenum target, - GLuint texture, - bool premultiply_alpha, - bool flip_y, - const IntPoint& dest_point, - const IntRect& source_sub_rectangle) { - if (!Extensions3DUtil::CanUseCopyTextureCHROMIUM(target)) - return false; - - if (!IsSurfaceValid()) - return false; - - scoped_refptr<StaticBitmapImage> image = - surface_->NewImageSnapshot(kPreferAcceleration, reason); - if (!image || !image->IsTextureBacked() || !image->IsValid()) - return false; - - // Get the texture ID, flushing pending operations if needed. - const GrGLTextureInfo* texture_info = skia::GrBackendObjectToGrGLTextureInfo( - image->PaintImageForCurrentFrame().GetSkImage()->getTextureHandle(true)); - if (!texture_info || !texture_info->fID) - return false; - - WebGraphicsContext3DProvider* provider = image->ContextProvider(); - if (!provider || !provider->GetGrContext()) - return false; - gpu::gles2::GLES2Interface* source_gl = provider->ContextGL(); - - gpu::Mailbox mailbox; - - // Contexts may be in a different share group. We must transfer the texture - // through a mailbox first. - source_gl->GenMailboxCHROMIUM(mailbox.name); - source_gl->ProduceTextureDirectCHROMIUM(texture_info->fID, mailbox.name); - const GLuint64 shared_fence_sync = source_gl->InsertFenceSyncCHROMIUM(); - source_gl->Flush(); - - gpu::SyncToken produce_sync_token; - source_gl->GenSyncTokenCHROMIUM(shared_fence_sync, - produce_sync_token.GetData()); - gl->WaitSyncTokenCHROMIUM(produce_sync_token.GetConstData()); - - GLuint source_texture = gl->CreateAndConsumeTextureCHROMIUM(mailbox.name); - - // The canvas is stored in a premultiplied format, so unpremultiply if - // necessary. The canvas is also stored in an inverted position, so the flip - // semantics are reversed. - // It is expected that callers of this method have already allocated - // the platform texture with the appropriate size. - gl->CopySubTextureCHROMIUM( - source_texture, 0, target, texture, 0, dest_point.X(), dest_point.Y(), - source_sub_rectangle.X(), source_sub_rectangle.Y(), - source_sub_rectangle.Width(), source_sub_rectangle.Height(), - flip_y ? GL_FALSE : GL_TRUE, GL_FALSE, - premultiply_alpha ? GL_FALSE : GL_TRUE); - - gl->DeleteTextures(1, &source_texture); - - const GLuint64 context_fence_sync = gl->InsertFenceSyncCHROMIUM(); - - gl->Flush(); - - gpu::SyncToken copy_sync_token; - gl->GenSyncTokenCHROMIUM(context_fence_sync, copy_sync_token.GetData()); - source_gl->WaitSyncTokenCHROMIUM(copy_sync_token.GetConstData()); - // This disassociates the texture from the mailbox to avoid leaking the - // mapping between the two in cases where the texture is recycled by skia. - source_gl->ProduceTextureDirectCHROMIUM(0, mailbox.name); - - // Undo grContext texture binding changes introduced in this function. - GrContext* gr_context = provider->GetGrContext(); - CHECK(gr_context); // We already check / early-out above if null. - gr_context->resetContext(kTextureBinding_GrGLBackendState); - - return true; -} - -bool ImageBuffer::CopyRenderingResultsFromDrawingBuffer( - DrawingBuffer* drawing_buffer, - SourceDrawingBuffer source_buffer) { - if (!drawing_buffer || !surface_->IsAccelerated()) - return false; - std::unique_ptr<WebGraphicsContext3DProvider> provider = - Platform::Current()->CreateSharedOffscreenGraphicsContext3DProvider(); - if (!provider) - return false; - gpu::gles2::GLES2Interface* gl = provider->ContextGL(); - GLuint texture_id = surface_->GetBackingTextureHandleForOverwrite(); - if (!texture_id) - return false; - - gl->Flush(); - - return drawing_buffer->CopyToPlatformTexture( - gl, GL_TEXTURE_2D, texture_id, true, false, IntPoint(0, 0), - IntRect(IntPoint(0, 0), drawing_buffer->Size()), source_buffer); -} - -void ImageBuffer::Draw(GraphicsContext& context, - const FloatRect& dest_rect, - const FloatRect* src_ptr, - SkBlendMode op) { - if (!IsSurfaceValid()) - return; - - FloatRect src_rect = - src_ptr ? *src_ptr : FloatRect(FloatPoint(), FloatSize(Size())); - surface_->Draw(context, dest_rect, src_rect, op); -} - -void ImageBuffer::PutByteArray(const unsigned char* source, - const IntSize& source_size, - const IntRect& source_rect, - const IntPoint& dest_point) { - if (!IsSurfaceValid()) - return; - uint8_t bytes_per_pixel = surface_->ColorParams().BytesPerPixel(); - - DCHECK_GT(source_rect.Width(), 0); - DCHECK_GT(source_rect.Height(), 0); - - int origin_x = source_rect.X(); - int dest_x = dest_point.X() + source_rect.X(); - DCHECK_GE(dest_x, 0); - DCHECK_LT(dest_x, surface_->Size().Width()); - DCHECK_GE(origin_x, 0); - DCHECK_LT(origin_x, source_rect.MaxX()); - - int origin_y = source_rect.Y(); - int dest_y = dest_point.Y() + source_rect.Y(); - DCHECK_GE(dest_y, 0); - DCHECK_LT(dest_y, surface_->Size().Height()); - DCHECK_GE(origin_y, 0); - DCHECK_LT(origin_y, source_rect.MaxY()); - - const size_t src_bytes_per_row = bytes_per_pixel * source_size.Width(); - const void* src_addr = - source + origin_y * src_bytes_per_row + origin_x * bytes_per_pixel; - - SkAlphaType alpha_type; - if (kOpaque == surface_->GetOpacityMode()) { - // If the surface is opaque, tell it that we are writing opaque - // pixels. Writing non-opaque pixels to opaque is undefined in - // Skia. There is some discussion about whether it should be - // defined in skbug.com/6157. For now, we can get the desired - // behavior (memcpy) by pretending the write is opaque. - alpha_type = kOpaque_SkAlphaType; - } else { - alpha_type = kUnpremul_SkAlphaType; - } - - SkImageInfo info; - if (surface_->ColorParams().GetSkColorSpaceForSkSurfaces()) { - info = SkImageInfo::Make( - source_rect.Width(), source_rect.Height(), - surface_->ColorParams().GetSkColorType(), alpha_type, - surface_->ColorParams().GetSkColorSpaceForSkSurfaces()); - if (info.colorType() == kN32_SkColorType) - info = info.makeColorType(kRGBA_8888_SkColorType); - } else { - info = SkImageInfo::Make(source_rect.Width(), source_rect.Height(), - kRGBA_8888_SkColorType, alpha_type); - } - surface_->WritePixels(info, src_addr, src_bytes_per_row, dest_x, dest_y); -} - -void ImageBuffer::SetSurface(std::unique_ptr<ImageBufferSurface> surface) { - scoped_refptr<StaticBitmapImage> image = - surface_->NewImageSnapshot(kPreferNoAcceleration, kSnapshotReasonPaint); - - // image can be null if alloaction failed in which case we should just - // abort the surface switch to reatain the old surface which is still - // functional. - if (!image) - return; - - surface->Canvas()->drawImage(image->PaintImageForCurrentFrame(), 0, 0); - surface->SetImageBuffer(this); - surface_ = std::move(surface); -} - -void ImageBuffer::OnCanvasDisposed() { - if (surface_) - surface_->SetCanvasResourceHost(nullptr); +bool ImageBuffer::WritePixels(const SkImageInfo& orig_info, + const void* pixels, + size_t row_bytes, + int x, + int y) { + return surface_->WritePixels(orig_info, pixels, row_bytes, x, y); } const unsigned char* ImageDataBuffer::Pixels() const {
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBuffer.h b/third_party/WebKit/Source/platform/graphics/ImageBuffer.h index 25062ef..65f79a32 100644 --- a/third_party/WebKit/Source/platform/graphics/ImageBuffer.h +++ b/third_party/WebKit/Source/platform/graphics/ImageBuffer.h
@@ -48,19 +48,8 @@ #include "platform/wtf/typed_arrays/Uint8ClampedArray.h" #include "third_party/skia/include/core/SkRefCnt.h" -namespace gpu { -namespace gles2 { -class GLES2Interface; -} -} - namespace blink { -class DrawingBuffer; -class GraphicsContext; -class IntPoint; -class IntRect; - class PLATFORM_EXPORT ImageBuffer { WTF_MAKE_NONCOPYABLE(ImageBuffer); USING_FAST_MALLOC(ImageBuffer); @@ -75,83 +64,32 @@ virtual ~ImageBuffer(); - static bool CanCreateImageBuffer(const IntSize&); const IntSize& Size() const { return surface_->Size(); } bool IsAccelerated() const { return surface_->IsAccelerated(); } - void PrepareSurfaceForPaintingIfNeeded() { - surface_->PrepareSurfaceForPaintingIfNeeded(); - } - bool IsSurfaceValid() const; - bool RestoreSurface() const; - void DidDraw(const FloatRect&) const; - bool WasDrawnToAfterSnapshot() const { - return snapshot_state_ == kDrawnToAfterSnapshot; - } - void SetFilterQuality(SkFilterQuality filter_quality) { - surface_->SetFilterQuality(filter_quality); - } - void SetIsHidden(bool hidden) { surface_->SetIsHidden(hidden); } + bool IsSurfaceValid() const; PaintCanvas* Canvas() const; - void DisableDeferral(DisableDeferralReason) const; - - // Called at the end of a task that rendered a whole frame - void FinalizeFrame(); - void DoPaintInvalidation(const FloatRect& dirty_rect); - - void WillOverwriteCanvas() { surface_->WillOverwriteCanvas(); } - - void PutByteArray(const unsigned char* source, - const IntSize& source_size, - const IntRect& source_rect, - const IntPoint& dest_point); - - WebLayer* PlatformLayer() const; - - // Destroys the TEXTURE_2D binding for the active texture unit of the passed - // context. Assumes the destination texture has already been allocated. - bool CopyToPlatformTexture(SnapshotReason, - gpu::gles2::GLES2Interface*, - GLenum target, - GLuint texture, - bool premultiply_alpha, - bool flip_y, - const IntPoint& dest_point, - const IntRect& source_sub_rectangle); - - bool CopyRenderingResultsFromDrawingBuffer(DrawingBuffer*, - SourceDrawingBuffer); scoped_refptr<StaticBitmapImage> NewImageSnapshot( AccelerationHint = kPreferNoAcceleration, SnapshotReason = kSnapshotReasonUnknown) const; - sk_sp<PaintRecord> GetRecord() { return surface_->GetRecord(); } - - void Draw(GraphicsContext&, const FloatRect&, const FloatRect*, SkBlendMode); - - void SetSurface(std::unique_ptr<ImageBufferSurface>); - - // TODO(xlai): This function is an intermediate step making canvas element - // have reference to Canvas2DLayerBridge. See crbug.com/776806. - void OnCanvasDisposed(); const CanvasColorParams& ColorParams() const { return surface_->ColorParams(); } base::WeakPtrFactory<ImageBuffer> weak_ptr_factory_; + bool WritePixels(const SkImageInfo& orig_info, + const void* pixels, + size_t row_bytes, + int x, + int y); protected: ImageBuffer(std::unique_ptr<ImageBufferSurface>); private: - enum SnapshotState { - kInitialSnapshotState, - kDidAcquireSnapshot, - kDrawnToAfterSnapshot, - }; - mutable SnapshotState snapshot_state_; std::unique_ptr<ImageBufferSurface> surface_; };
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.cpp b/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.cpp index 2441fed..41b6cd7 100644 --- a/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.cpp +++ b/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.cpp
@@ -30,10 +30,8 @@ #include "platform/graphics/ImageBufferSurface.h" -#include "platform/graphics/GraphicsContext.h" #include "platform/graphics/ImageBuffer.h" #include "platform/graphics/StaticBitmapImage.h" -#include "third_party/skia/include/core/SkColorSpace.h" #include "third_party/skia/include/core/SkImage.h" @@ -42,15 +40,10 @@ ImageBufferSurface::ImageBufferSurface(const IntSize& size, const CanvasColorParams& color_params) : size_(size), color_params_(color_params) { - SetIsHidden(false); } ImageBufferSurface::~ImageBufferSurface() {} -sk_sp<PaintRecord> ImageBufferSurface::GetRecord() { - return nullptr; -} - void ImageBufferSurface::Clear() { // Clear the background transparent or opaque, as required. It would be nice // if this wasn't required, but the canvas is currently filled with the magic @@ -61,25 +54,7 @@ } else { Canvas()->clear(SK_ColorTRANSPARENT); } - DidDraw(FloatRect(FloatPoint(0, 0), FloatSize(Size()))); } } -void ImageBufferSurface::Draw(GraphicsContext& context, - const FloatRect& dest_rect, - const FloatRect& src_rect, - SkBlendMode op) { - scoped_refptr<StaticBitmapImage> snapshot = - NewImageSnapshot(kPreferAcceleration, kSnapshotReasonPaint); - if (!snapshot) - return; - - // GraphicsContext cannot handle gpu resource serialization. - snapshot = snapshot->MakeUnaccelerated(); - - DCHECK(!snapshot->IsTextureBacked()); - context.DrawImage(snapshot.get(), Image::kSyncDecode, dest_rect, &src_rect, - op); -} - } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.h b/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.h index 2129f67f..fbb7079 100644 --- a/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.h +++ b/third_party/WebKit/Source/platform/graphics/ImageBufferSurface.h
@@ -36,24 +36,16 @@ #include "platform/graphics/CanvasColorParams.h" #include "platform/graphics/GraphicsTypes.h" #include "platform/graphics/paint/PaintCanvas.h" -#include "platform/graphics/paint/PaintFlags.h" -#include "platform/graphics/paint/PaintRecord.h" #include "platform/wtf/Allocator.h" #include "platform/wtf/Noncopyable.h" -#include "third_party/khronos/GLES2/gl2.h" -#include "third_party/skia/include/core/SkImageInfo.h" #include "third_party/skia/include/core/SkRefCnt.h" struct SkImageInfo; namespace blink { -class CanvasResourceHost; -class FloatRect; -class GraphicsContext; class ImageBuffer; class StaticBitmapImage; -class WebLayer; class PLATFORM_EXPORT ImageBufferSurface { WTF_MAKE_NONCOPYABLE(ImageBufferSurface); @@ -63,44 +55,23 @@ virtual ~ImageBufferSurface(); virtual PaintCanvas* Canvas() = 0; - virtual void DisableDeferral(DisableDeferralReason) {} - virtual void WillOverwriteCanvas() {} - virtual void DidDraw(const FloatRect& rect) {} virtual bool IsValid() const = 0; - virtual bool Restore() { return false; } - virtual WebLayer* Layer() { return nullptr; } virtual bool IsAccelerated() const { return false; } - virtual void SetFilterQuality(SkFilterQuality) {} - virtual void SetIsHidden(bool) {} virtual void SetImageBuffer(ImageBuffer*) {} - virtual sk_sp<PaintRecord> GetRecord(); - virtual void FinalizeFrame() {} - virtual void DoPaintInvalidation(const FloatRect& dirty_rect) {} - virtual void Draw(GraphicsContext&, - const FloatRect& dest_rect, - const FloatRect& src_rect, - SkBlendMode); - virtual void SetHasExpensiveOp() {} - virtual GLuint GetBackingTextureHandleForOverwrite() { return 0; } - virtual void PrepareSurfaceForPaintingIfNeeded() {} virtual bool WritePixels(const SkImageInfo& orig_info, const void* pixels, size_t row_bytes, int x, int y) = 0; - virtual void SetCanvasResourceHost(CanvasResourceHost*) {} // May return nullptr if the surface is GPU-backed and the GPU context was // lost. virtual scoped_refptr<StaticBitmapImage> NewImageSnapshot(AccelerationHint, SnapshotReason) = 0; - OpacityMode GetOpacityMode() const { return color_params_.GetOpacityMode(); } const IntSize& Size() const { return size_; } const CanvasColorParams& ColorParams() const { return color_params_; } - void NotifyIsValidChanged(bool is_valid) const; - protected: ImageBufferSurface(const IntSize&, const CanvasColorParams&); void Clear();
diff --git a/third_party/WebKit/Source/platform/graphics/MailboxTextureHolder.cpp b/third_party/WebKit/Source/platform/graphics/MailboxTextureHolder.cpp index f601bf7fb..06a9ef8b 100644 --- a/third_party/WebKit/Source/platform/graphics/MailboxTextureHolder.cpp +++ b/third_party/WebKit/Source/platform/graphics/MailboxTextureHolder.cpp
@@ -95,13 +95,10 @@ } if (!sync_token_.HasData()) { - const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM(); if (mode == kVerifiedSyncToken) { - gl->ShallowFlushCHROMIUM(); - gl->GenSyncTokenCHROMIUM(fence_sync, sync_token_.GetData()); + gl->GenSyncTokenCHROMIUM(sync_token_.GetData()); } else { - gl->OrderingBarrierCHROMIUM(); - gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token_.GetData()); + gl->GenUnverifiedSyncTokenCHROMIUM(sync_token_.GetData()); } return; }
diff --git a/third_party/WebKit/Source/platform/graphics/StaticBitmapImage.cpp b/third_party/WebKit/Source/platform/graphics/StaticBitmapImage.cpp index d43e33d..96f8126 100644 --- a/third_party/WebKit/Source/platform/graphics/StaticBitmapImage.cpp +++ b/third_party/WebKit/Source/platform/graphics/StaticBitmapImage.cpp
@@ -4,6 +4,7 @@ #include "platform/graphics/StaticBitmapImage.h" +#include "gpu/command_buffer/client/gles2_interface.h" #include "platform/graphics/AcceleratedStaticBitmapImage.h" #include "platform/graphics/GraphicsContext.h" #include "platform/graphics/ImageObserver.h" @@ -11,9 +12,11 @@ #include "platform/graphics/paint/PaintImage.h" #include "platform/wtf/CheckedNumeric.h" #include "platform/wtf/typed_arrays/ArrayBufferContents.h" +#include "skia/ext/texture_handle.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkPaint.h" +#include "third_party/skia/include/gpu/GrContext.h" namespace blink { @@ -157,4 +160,73 @@ return sync_token; } +bool StaticBitmapImage::CopyImageToPlatformTexture( + gpu::gles2::GLES2Interface* gl, + GLenum target, + GLuint texture, + bool premultiply_alpha, + bool flip_y, + const IntPoint& dest_point, + const IntRect& source_sub_rectangle) { + if (!IsTextureBacked() || !IsValid()) + return false; + + // Get the texture ID, flushing pending operations if needed. + const GrGLTextureInfo* texture_info = skia::GrBackendObjectToGrGLTextureInfo( + PaintImageForCurrentFrame().GetSkImage()->getTextureHandle(true)); + if (!texture_info || !texture_info->fID) + return false; + + WebGraphicsContext3DProvider* provider = ContextProvider(); + if (!provider || !provider->GetGrContext()) + return false; + gpu::gles2::GLES2Interface* source_gl = provider->ContextGL(); + + gpu::Mailbox mailbox; + + // Contexts may be in a different share group. We must transfer the texture + // through a mailbox first. + source_gl->GenMailboxCHROMIUM(mailbox.name); + source_gl->ProduceTextureDirectCHROMIUM(texture_info->fID, mailbox.name); + // TODO(xlai): This one might need to be replaced with ShallowFlushCHROMIUM(). + // See crbug.com/794706. + source_gl->Flush(); + + gpu::SyncToken produce_sync_token; + source_gl->GenSyncTokenCHROMIUM(produce_sync_token.GetData()); + gl->WaitSyncTokenCHROMIUM(produce_sync_token.GetConstData()); + + GLuint source_texture = gl->CreateAndConsumeTextureCHROMIUM(mailbox.name); + + // The canvas is stored in a premultiplied format, so unpremultiply if + // necessary. The canvas is also stored in an inverted position, so the flip + // semantics are reversed. + // It is expected that callers of this method have already allocated + // the platform texture with the appropriate size. + gl->CopySubTextureCHROMIUM( + source_texture, 0, target, texture, 0, dest_point.X(), dest_point.Y(), + source_sub_rectangle.X(), source_sub_rectangle.Y(), + source_sub_rectangle.Width(), source_sub_rectangle.Height(), + flip_y ? GL_FALSE : GL_TRUE, GL_FALSE, + premultiply_alpha ? GL_FALSE : GL_TRUE); + + gl->DeleteTextures(1, &source_texture); + + gl->Flush(); + + gpu::SyncToken copy_sync_token; + gl->GenSyncTokenCHROMIUM(copy_sync_token.GetData()); + source_gl->WaitSyncTokenCHROMIUM(copy_sync_token.GetConstData()); + // This disassociates the texture from the mailbox to avoid leaking the + // mapping between the two in cases where the texture is recycled by skia. + source_gl->ProduceTextureDirectCHROMIUM(0, mailbox.name); + + // Undo grContext texture binding changes introduced in this function. + GrContext* gr_context = provider->GetGrContext(); + CHECK(gr_context); // We already check / early-out above if null. + gr_context->resetContext(kTextureBinding_GrGLBackendState); + + return true; +} + } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/StaticBitmapImage.h b/third_party/WebKit/Source/platform/graphics/StaticBitmapImage.h index 8fa1a4c3..73caa51 100644 --- a/third_party/WebKit/Source/platform/graphics/StaticBitmapImage.h +++ b/third_party/WebKit/Source/platform/graphics/StaticBitmapImage.h
@@ -21,6 +21,12 @@ } // namespace WTF +namespace gpu { +namespace gles2 { +class GLES2Interface; +} +} // namespace gpu + namespace blink { class WebGraphicsContext3DProvider; @@ -75,6 +81,18 @@ const IntRect&) { NOTREACHED(); } + // TODO: Merge CopyImageToPlatformTexture function with CopyToTexture + // function above and probably with CopyToPlatformTexture in DrawingBuffer + // too. See crbug.com/794706. + // Destroys the TEXTURE_2D binding for the active texture unit of the passed + // context. Assumes the destination texture has already been allocated. + bool CopyImageToPlatformTexture(gpu::gles2::GLES2Interface*, + GLenum target, + GLuint texture, + bool premultiply_alpha, + bool flip_y, + const IntPoint& dest_point, + const IntRect& source_sub_rectangle); // EnsureMailbox modifies the internal state of an accelerated static bitmap // image to make sure that it is represented by a Mailbox. This must be
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.h b/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.h index e2dd600..e01fbc6 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.h +++ b/third_party/WebKit/Source/platform/graphics/gpu/AcceleratedImageBufferSurface.h
@@ -36,6 +36,7 @@ #include "platform/graphics/ImageBufferSurface.h" #include "platform/graphics/paint/PaintCanvas.h" #include "public/platform/WebGraphicsContext3DProvider.h" +#include "third_party/khronos/GLES2/gl2.h" #include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/skia/include/core/SkSurface.h" @@ -58,7 +59,7 @@ bool IsAccelerated() const override { return true; } scoped_refptr<StaticBitmapImage> NewImageSnapshot(AccelerationHint, SnapshotReason) override; - GLuint GetBackingTextureHandleForOverwrite() override; + GLuint GetBackingTextureHandleForOverwrite(); bool WritePixels(const SkImageInfo& orig_info, const void* pixels, size_t row_bytes,
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp index 8167474..ebd3833 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBuffer.cpp
@@ -391,17 +391,15 @@ { gl_->ProduceTextureDirectCHROMIUM(color_buffer_for_mailbox->texture_id, color_buffer_for_mailbox->mailbox.name); - const GLuint64 fence_sync = gl_->InsertFenceSyncCHROMIUM(); // It's critical to order the execution of this context's work relative // to other contexts, in particular the compositor. Previously this // used to be a Flush, and there was a bug that we didn't flush before - // InsertFenceSyncCHROMIUM, above. On some platforms this caused + // synchronizing with the composition, and on some platforms this caused // incorrect rendering with complex WebGL content that wasn't always // properly flushed to the driver. There is now a basic assumption that // there are implicit flushes between contexts at the lowest level. - gl_->OrderingBarrierCHROMIUM(); gl_->GenUnverifiedSyncTokenCHROMIUM( - fence_sync, color_buffer_for_mailbox->produce_sync_token.GetData()); + color_buffer_for_mailbox->produce_sync_token.GetData()); #if defined(OS_MACOSX) // Needed for GPU back-pressure on macOS. Used to be in the middle // of the commands above; try to move it to the bottom to allow @@ -778,10 +776,7 @@ src_gl->GenMailboxCHROMIUM(mailbox.name); src_gl->ProduceTextureDirectCHROMIUM(back_color_buffer_->texture_id, mailbox.name); - const GLuint64 fence_sync = src_gl->InsertFenceSyncCHROMIUM(); - src_gl->OrderingBarrierCHROMIUM(); - src_gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, - produce_sync_token.GetData()); + src_gl->GenUnverifiedSyncTokenCHROMIUM(produce_sync_token.GetData()); } if (!produce_sync_token.HasData()) { @@ -808,11 +803,8 @@ dst_gl->DeleteTextures(1, &src_texture); - const GLuint64 fence_sync = dst_gl->InsertFenceSyncCHROMIUM(); - - dst_gl->OrderingBarrierCHROMIUM(); gpu::SyncToken sync_token; - dst_gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + dst_gl->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); src_gl->WaitSyncTokenCHROMIUM(sync_token.GetData()); return true;
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp index a0f5423..0d90af5 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTest.cpp
@@ -372,8 +372,7 @@ EXPECT_EQ(gpu::SyncToken(), gl_->MostRecentlyWaitedSyncToken()); gpu::SyncToken wait_sync_token; - gl_->GenSyncTokenCHROMIUM(gl_->InsertFenceSyncCHROMIUM(), - wait_sync_token.GetData()); + gl_->GenSyncTokenCHROMIUM(wait_sync_token.GetData()); release_callback->Run(wait_sync_token, false /* lostResource */); // m_drawingBuffer will wait for the sync point when recycling. EXPECT_EQ(gpu::SyncToken(), gl_->MostRecentlyWaitedSyncToken()); @@ -386,8 +385,7 @@ EXPECT_EQ(wait_sync_token, gl_->MostRecentlyWaitedSyncToken()); drawing_buffer_->BeginDestruction(); - gl_->GenSyncTokenCHROMIUM(gl_->InsertFenceSyncCHROMIUM(), - wait_sync_token.GetData()); + gl_->GenSyncTokenCHROMIUM(wait_sync_token.GetData()); release_callback->Run(wait_sync_token, false /* lostResource */); // m_drawingBuffer waits for the sync point because the destruction is in // progress. @@ -724,8 +722,7 @@ &release_callback)); gpu::SyncToken wait_sync_token; - gl_->GenSyncTokenCHROMIUM(gl_->InsertFenceSyncCHROMIUM(), - wait_sync_token.GetData()); + gl_->GenSyncTokenCHROMIUM(wait_sync_token.GetData()); drawing_buffer_->SetIsHidden(true); release_callback->Run(wait_sync_token, false /* lostResource */); // m_drawingBuffer deletes resource immediately when hidden.
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTestHelpers.h b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTestHelpers.h index cff2518..e4226993 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTestHelpers.h +++ b/third_party/WebKit/Source/platform/graphics/gpu/DrawingBufferTestHelpers.h
@@ -169,11 +169,6 @@ } } - GLuint64 InsertFenceSyncCHROMIUM() override { - static GLuint64 sync_point_generator = 0; - return ++sync_point_generator; - } - void WaitSyncTokenCHROMIUM(const GLbyte* sync_token) override { memcpy(&most_recently_waited_sync_token_, sync_token, sizeof(most_recently_waited_sync_token_)); @@ -263,7 +258,7 @@ } } - void GenSyncTokenCHROMIUM(GLuint64 fence_sync, GLbyte* sync_token) override { + void GenSyncTokenCHROMIUM(GLbyte* sync_token) override { static uint64_t unique_id = 1; gpu::SyncToken source( gpu::GPU_IO, 1, gpu::CommandBufferId::FromUnsafeValue(unique_id++), 2);
diff --git a/third_party/WebKit/Source/platform/graphics/gpu/SharedGpuContextTest.cpp b/third_party/WebKit/Source/platform/graphics/gpu/SharedGpuContextTest.cpp index 99ad653..b8f27f4 100644 --- a/third_party/WebKit/Source/platform/graphics/gpu/SharedGpuContextTest.cpp +++ b/third_party/WebKit/Source/platform/graphics/gpu/SharedGpuContextTest.cpp
@@ -45,9 +45,8 @@ class MailboxMockGLES2Interface : public FakeGLES2Interface { public: MOCK_METHOD1(GenMailboxCHROMIUM, void(GLbyte*)); - MOCK_METHOD2(GenSyncTokenCHROMIUM, void(GLuint64, GLbyte*)); - MOCK_METHOD2(GenUnverifiedSyncTokenCHROMIUM, void(GLuint64, GLbyte*)); - MOCK_METHOD0(InsertFenceSyncCHROMIUM, GLuint64(void)); + MOCK_METHOD1(GenSyncTokenCHROMIUM, void(GLbyte*)); + MOCK_METHOD1(GenUnverifiedSyncTokenCHROMIUM, void(GLbyte*)); }; class MailboxSharedGpuContextTest
diff --git a/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.cpp b/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.cpp index 66bbf95..f7bea7f4 100644 --- a/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.cpp +++ b/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.cpp
@@ -198,6 +198,18 @@ return fabs(value - floorf(value)) < std::numeric_limits<float>::epsilon(); } +bool IsValidImageSize(const IntSize& size) { + if (size.IsEmpty()) + return false; + base::CheckedNumeric<int> area = size.Width(); + area *= size.Height(); + if (!area.IsValid() || area.ValueOrDie() > kMaxCanvasArea) + return false; + if (size.Width() > kMaxSkiaDim || size.Height() > kMaxSkiaDim) + return false; + return true; +} + InterpolationQuality ComputeInterpolationQuality(float src_width, float src_height, float dest_width,
diff --git a/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.h b/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.h index 278cb59..2b33580 100644 --- a/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.h +++ b/third_party/WebKit/Source/platform/graphics/skia/SkiaUtils.h
@@ -58,6 +58,8 @@ kMaxSkiaDim = 32767 // Maximum width/height in CSS pixels. }; +bool PLATFORM_EXPORT IsValidImageSize(const IntSize&); + SkBlendMode PLATFORM_EXPORT WebCoreCompositeToSkiaComposite(CompositeOperator, WebBlendMode = WebBlendMode::kNormal);
diff --git a/third_party/WebKit/Source/platform/instrumentation/BUILD.gn b/third_party/WebKit/Source/platform/instrumentation/BUILD.gn index 392e6c8..4ae1d2ab 100644 --- a/third_party/WebKit/Source/platform/instrumentation/BUILD.gn +++ b/third_party/WebKit/Source/platform/instrumentation/BUILD.gn
@@ -15,6 +15,7 @@ "resource_coordinator/RendererResourceCoordinator.h", "tracing/MemoryCacheDumpProvider.cpp", "tracing/MemoryCacheDumpProvider.h", + "tracing/TraceEvent.cpp", "tracing/TraceEvent.h", "tracing/TracedValue.cpp", "tracing/TracedValue.h",
diff --git a/third_party/WebKit/Source/platform/instrumentation/tracing/TraceEvent.cpp b/third_party/WebKit/Source/platform/instrumentation/tracing/TraceEvent.cpp new file mode 100644 index 0000000..682f418 --- /dev/null +++ b/third_party/WebKit/Source/platform/instrumentation/tracing/TraceEvent.cpp
@@ -0,0 +1,23 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "platform/instrumentation/tracing/TraceEvent.h" + +#include "base/trace_event/trace_event.h" + +namespace blink { +namespace TraceEvent { + +void EnableTracing(const String& category_filter) { + base::trace_event::TraceLog::GetInstance()->SetEnabled( + base::trace_event::TraceConfig(category_filter.Utf8().data(), ""), + base::trace_event::TraceLog::RECORDING_MODE); +} + +void DisableTracing() { + base::trace_event::TraceLog::GetInstance()->SetDisabled(); +} + +} // namespace TraceEvent +} // namespace blink
diff --git a/third_party/WebKit/Source/platform/instrumentation/tracing/TraceEvent.h b/third_party/WebKit/Source/platform/instrumentation/tracing/TraceEvent.h index 9114868..57ba80a 100644 --- a/third_party/WebKit/Source/platform/instrumentation/tracing/TraceEvent.h +++ b/third_party/WebKit/Source/platform/instrumentation/tracing/TraceEvent.h
@@ -7,7 +7,9 @@ #include "base/time/time.h" #include "base/trace_event/trace_event.h" +#include "platform/PlatformExport.h" #include "platform/wtf/text/CString.h" +#include "platform/wtf/text/WTFString.h" namespace WTF { @@ -35,6 +37,9 @@ // This is to avoid error of passing a chromium time internal value. void ToTraceTimestamp(int64_t); +PLATFORM_EXPORT void EnableTracing(const String& category_filter); +PLATFORM_EXPORT void DisableTracing(); + } // namespace TraceEvent } // namespace blink
diff --git a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp index 7128d1b..bc2706d2 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp +++ b/third_party/WebKit/Source/platform/loader/fetch/Resource.cpp
@@ -286,9 +286,6 @@ resource_request_(request) { InstanceCounters::IncrementCounter(InstanceCounters::kResourceCounter); - // Currently we support the metadata caching only for HTTP family. - if (GetResourceRequest().Url().ProtocolIsInHTTPFamily()) - cache_handler_ = CachedMetadataHandlerImpl::Create(this); if (IsMainThread()) MemoryCoordinator::Instance().RegisterClient(this); } @@ -566,14 +563,19 @@ void Resource::SetResponse(const ResourceResponse& response) { response_ = response; + // Currently we support the metadata caching only for HTTP family. - if (!GetResponse().Url().ProtocolIsInHTTPFamily()) { + if (!GetResourceRequest().Url().ProtocolIsInHTTPFamily() || + !GetResponse().Url().ProtocolIsInHTTPFamily()) { cache_handler_.Clear(); return; } + if (GetResponse().WasFetchedViaServiceWorker()) { cache_handler_ = ServiceWorkerResponseCachedMetadataHandler::Create( this, fetcher_security_origin_.get()); + } else { + cache_handler_ = CachedMetadataHandlerImpl::Create(this); } }
diff --git a/third_party/WebKit/Source/platform/loader/fetch/ResourceTest.cpp b/third_party/WebKit/Source/platform/loader/fetch/ResourceTest.cpp index bea5830..207c7e9 100644 --- a/third_party/WebKit/Source/platform/loader/fetch/ResourceTest.cpp +++ b/third_party/WebKit/Source/platform/loader/fetch/ResourceTest.cpp
@@ -179,9 +179,7 @@ EXPECT_FALSE(resource->IsCacheValidator()); EXPECT_EQ(200, resource->GetResponse().HttpStatusCode()); EXPECT_FALSE(resource->ResourceBuffer()); - // TODO(hiroshige): Currently CachedMetadataHandler is cleared on - // revalidation. Enable this check once fixed. crbug.com/784875 - // EXPECT_TRUE(resource->CacheHandler()); + EXPECT_TRUE(resource->CacheHandler()); EXPECT_NE(original_cache_handler, resource->CacheHandler()); EXPECT_EQ(resource, GetMemoryCache()->ResourceForURL(url)); @@ -394,9 +392,7 @@ revalidating_response.SetHTTPStatusCode(200); resource->ResponseReceived(revalidating_response, nullptr); - // TODO(hiroshige): Currently CachedMetadataHandler is cleared on - // revalidation. Enable this check once fixed. crbug.com/784875 - // EXPECT_TRUE(resource->CacheHandler()); + EXPECT_TRUE(resource->CacheHandler()); const char kData2[4] = "xyz"; resource->AppendData(kData2, 3);
diff --git a/third_party/WebKit/Source/platform/runtime_enabled_features.json5 b/third_party/WebKit/Source/platform/runtime_enabled_features.json5 index 134c512..8d32a0a 100644 --- a/third_party/WebKit/Source/platform/runtime_enabled_features.json5 +++ b/third_party/WebKit/Source/platform/runtime_enabled_features.json5
@@ -334,7 +334,7 @@ }, { name: "DisplayNoneIFrameCreatesNoLayoutObject", - status: "experimental", + status: "stable", }, { name: "DocumentCookie",
diff --git a/third_party/WebKit/Source/platform/scheduler/BUILD.gn b/third_party/WebKit/Source/platform/scheduler/BUILD.gn index 745ac70..e30e8206 100644 --- a/third_party/WebKit/Source/platform/scheduler/BUILD.gn +++ b/third_party/WebKit/Source/platform/scheduler/BUILD.gn
@@ -115,6 +115,8 @@ "renderer/webthread_impl_for_renderer_scheduler.cc", "renderer/webthread_impl_for_renderer_scheduler.h", "util/task_duration_metric_reporter.h", + "util/thread_cpu_throttler.cc", + "util/thread_cpu_throttler.h", "util/thread_load_tracker.cc", "util/thread_load_tracker.h", "util/thread_type.h",
diff --git a/third_party/WebKit/Source/platform/scheduler/DEPS b/third_party/WebKit/Source/platform/scheduler/DEPS index 7dbb33a..4139e92 100644 --- a/third_party/WebKit/Source/platform/scheduler/DEPS +++ b/third_party/WebKit/Source/platform/scheduler/DEPS
@@ -24,6 +24,7 @@ "+base/single_thread_task_runner.h", "+base/strings/string_number_conversions.h", "+base/synchronization/atomic_flag.h", + "+base/synchronization/cancellation_flag.h", "+base/synchronization/lock.h", "+base/threading/platform_thread.h", "+base/threading/thread.h",
diff --git a/content/renderer/devtools/devtools_cpu_throttler.cc b/third_party/WebKit/Source/platform/scheduler/util/thread_cpu_throttler.cc similarity index 72% rename from content/renderer/devtools/devtools_cpu_throttler.cc rename to third_party/WebKit/Source/platform/scheduler/util/thread_cpu_throttler.cc index 9769a07..accbf40 100644 --- a/content/renderer/devtools/devtools_cpu_throttler.cc +++ b/third_party/WebKit/Source/platform/scheduler/util/thread_cpu_throttler.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/devtools/devtools_cpu_throttler.h" +#include "platform/scheduler/util/thread_cpu_throttler.h" #include "base/atomicops.h" #include "base/macros.h" @@ -20,12 +20,14 @@ using base::subtle::Acquire_Load; using base::subtle::Release_Store; -namespace content { +namespace blink { +namespace scheduler { -class CPUThrottlingThread final : public base::PlatformThread::Delegate { +class ThreadCPUThrottler::ThrottlingThread final + : public base::PlatformThread::Delegate { public: - explicit CPUThrottlingThread(double rate); - ~CPUThrottlingThread() override; + explicit ThrottlingThread(double rate); + ~ThrottlingThread() override; void SetThrottlingRate(double rate); @@ -55,17 +57,17 @@ base::PlatformThreadHandle throttling_thread_handle_; base::CancellationFlag cancellation_flag_; - DISALLOW_COPY_AND_ASSIGN(CPUThrottlingThread); + DISALLOW_COPY_AND_ASSIGN(ThrottlingThread); }; #ifdef USE_SIGNALS -bool CPUThrottlingThread::signal_handler_installed_; -struct sigaction CPUThrottlingThread::old_signal_handler_; +bool ThreadCPUThrottler::ThrottlingThread::signal_handler_installed_; +struct sigaction ThreadCPUThrottler::ThrottlingThread::old_signal_handler_; #endif -Atomic32 CPUThrottlingThread::throttling_rate_percent_; -Atomic32 CPUThrottlingThread::thread_exists_; +Atomic32 ThreadCPUThrottler::ThrottlingThread::throttling_rate_percent_; +Atomic32 ThreadCPUThrottler::ThrottlingThread::thread_exists_; -CPUThrottlingThread::CPUThrottlingThread(double rate) +ThreadCPUThrottler::ThrottlingThread::ThrottlingThread(double rate) #ifdef OS_WIN : throttled_thread_handle_( ::OpenThread(THREAD_SUSPEND_RESUME, false, ::GetCurrentThreadId())) { @@ -77,17 +79,17 @@ Start(); } -CPUThrottlingThread::~CPUThrottlingThread() { +ThreadCPUThrottler::ThrottlingThread::~ThrottlingThread() { Stop(); CHECK(base::subtle::NoBarrier_AtomicExchange(&thread_exists_, 0) == 1); } -void CPUThrottlingThread::SetThrottlingRate(double rate) { +void ThreadCPUThrottler::ThrottlingThread::SetThrottlingRate(double rate) { Release_Store(&throttling_rate_percent_, static_cast<Atomic32>(rate * 100)); } -void CPUThrottlingThread::ThreadMain() { - base::PlatformThread::SetName("DevToolsCPUThrottlingThread"); +void ThreadCPUThrottler::ThrottlingThread::ThreadMain() { + base::PlatformThread::SetName("CPUThrottlingThread"); while (!cancellation_flag_.IsSet()) { Throttle(); } @@ -96,7 +98,7 @@ #ifdef USE_SIGNALS // static -void CPUThrottlingThread::InstallSignalHandler() { +void ThreadCPUThrottler::ThrottlingThread::InstallSignalHandler() { // There must be the only one! DCHECK(!signal_handler_installed_); struct sigaction sa; @@ -108,7 +110,7 @@ } // static -void CPUThrottlingThread::RestoreSignalHandler() { +void ThreadCPUThrottler::ThrottlingThread::RestoreSignalHandler() { if (!signal_handler_installed_) return; sigaction(SIGUSR2, &old_signal_handler_, nullptr); @@ -116,7 +118,7 @@ } // static -void CPUThrottlingThread::HandleSignal(int signal) { +void ThreadCPUThrottler::ThrottlingThread::HandleSignal(int signal) { if (signal != SIGUSR2) return; static base::TimeTicks lastResumeTime; @@ -139,7 +141,7 @@ #endif // USE_SIGNALS -void CPUThrottlingThread::Throttle() { +void ThreadCPUThrottler::ThrottlingThread::Throttle() { const int quant_time_us = 200; #if defined(OS_WIN) double rate = Acquire_Load(&throttling_rate_percent_) / 100.; @@ -157,7 +159,7 @@ #endif } -void CPUThrottlingThread::Start() { +void ThreadCPUThrottler::ThrottlingThread::Start() { #ifdef USE_SIGNALS InstallSignalHandler(); #elif !defined(OS_WIN) @@ -168,18 +170,19 @@ } } -void CPUThrottlingThread::Sleep(base::TimeDelta duration) { +void ThreadCPUThrottler::ThrottlingThread::Sleep(base::TimeDelta duration) { #if defined(OS_WIN) // We cannot rely on ::Sleep function as it's precision is not enough for // the purpose. Could be up to 16ms jitter. base::TimeTicks wakeup_time = base::TimeTicks::Now() + duration; - while (base::TimeTicks::Now() < wakeup_time) {} + while (base::TimeTicks::Now() < wakeup_time) { + } #else base::PlatformThread::Sleep(duration); #endif } -void CPUThrottlingThread::Stop() { +void ThreadCPUThrottler::ThrottlingThread::Stop() { cancellation_flag_.Set(); base::PlatformThread::Join(throttling_thread_handle_); #ifdef USE_SIGNALS @@ -187,10 +190,10 @@ #endif } -DevToolsCPUThrottler::DevToolsCPUThrottler() = default; -DevToolsCPUThrottler::~DevToolsCPUThrottler() = default; +ThreadCPUThrottler::ThreadCPUThrottler() = default; +ThreadCPUThrottler::~ThreadCPUThrottler() = default; -void DevToolsCPUThrottler::SetThrottlingRate(double rate) { +void ThreadCPUThrottler::SetThrottlingRate(double rate) { if (rate <= 1) { if (throttling_thread_) { throttling_thread_.reset(); @@ -200,13 +203,14 @@ if (throttling_thread_) { throttling_thread_->SetThrottlingRate(rate); } else { - throttling_thread_.reset(new CPUThrottlingThread(rate)); + throttling_thread_.reset(new ThrottlingThread(rate)); } } // static -DevToolsCPUThrottler* DevToolsCPUThrottler::GetInstance() { - return base::Singleton<DevToolsCPUThrottler>::get(); +ThreadCPUThrottler* ThreadCPUThrottler::GetInstance() { + return base::Singleton<ThreadCPUThrottler>::get(); } -} // namespace content +} // namespace scheduler +} // namespace blink
diff --git a/third_party/WebKit/Source/platform/scheduler/util/thread_cpu_throttler.h b/third_party/WebKit/Source/platform/scheduler/util/thread_cpu_throttler.h new file mode 100644 index 0000000..a50c937 --- /dev/null +++ b/third_party/WebKit/Source/platform/scheduler/util/thread_cpu_throttler.h
@@ -0,0 +1,49 @@ +// 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 THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_UTIL_THREAD_CPU_THROTTLER_H_ +#define THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_UTIL_THREAD_CPU_THROTTLER_H_ + +#include <memory> + +#include "base/macros.h" +#include "platform/PlatformExport.h" + +namespace base { +template <typename T> +struct DefaultSingletonTraits; +}; + +namespace blink { +namespace scheduler { + +// This class is used to slow down the main thread for +// inspector "cpu throttling". It does it by spawning an +// additional thread which frequently interrupts main thread +// and sleeps. +class PLATFORM_EXPORT ThreadCPUThrottler final { + public: + static ThreadCPUThrottler* GetInstance(); + + // |rate| is a slow-down factor - passing 2.0 will make + // everything two times slower. + // Any rate less or equal to 1.0 disables throttling and + // cleans up helper thread. + void SetThrottlingRate(double rate); + + private: + ThreadCPUThrottler(); + ~ThreadCPUThrottler(); + friend struct base::DefaultSingletonTraits<ThreadCPUThrottler>; + + class ThrottlingThread; + std::unique_ptr<ThrottlingThread> throttling_thread_; + + DISALLOW_COPY_AND_ASSIGN(ThreadCPUThrottler); +}; + +} // namespace scheduler +} // namespace blink + +#endif // THIRD_PARTY_WEBKIT_SOURCE_PLATFORM_SCHEDULER_UTIL_THREAD_CPU_THROTTLER_H_
diff --git a/third_party/WebKit/Source/platform/text/Character.cpp b/third_party/WebKit/Source/platform/text/Character.cpp index 4042267..b37b8c7 100644 --- a/third_party/WebKit/Source/platform/text/Character.cpp +++ b/third_party/WebKit/Source/platform/text/Character.cpp
@@ -110,11 +110,7 @@ RETURN_HAS_PROPERTY(character, kIsUprightInMixedVertical) } -bool Character::IsCJKIdeographOrSymbol(UChar32 c) { - // Likely common case - if (c < 0x2C7) - return false; - +bool Character::IsCJKIdeographOrSymbolSlow(UChar32 c) { RETURN_HAS_PROPERTY(c, kIsCJKIdeographOrSymbol) } @@ -219,16 +215,12 @@ switch (block) { // These blocks contain CJK characters we don't want to skip ink, but are // not ideograph that IsCJKIdeographOrSymbol() does not cover. - case UBLOCK_BOPOMOFO: - case UBLOCK_BOPOMOFO_EXTENDED: case UBLOCK_HANGUL_JAMO: case UBLOCK_HANGUL_COMPATIBILITY_JAMO: case UBLOCK_HANGUL_SYLLABLES: case UBLOCK_HANGUL_JAMO_EXTENDED_A: case UBLOCK_HANGUL_JAMO_EXTENDED_B: case UBLOCK_LINEAR_B_IDEOGRAMS: - case UBLOCK_TANGUT: - case UBLOCK_TANGUT_COMPONENTS: return false; default: return true;
diff --git a/third_party/WebKit/Source/platform/text/Character.h b/third_party/WebKit/Source/platform/text/Character.h index 8289a4c..d617f2a2 100644 --- a/third_party/WebKit/Source/platform/text/Character.h +++ b/third_party/WebKit/Source/platform/text/Character.h
@@ -63,7 +63,10 @@ 0xE01EF); // VARIATION SELECTOR-17 to 256 } - static bool IsCJKIdeographOrSymbol(UChar32); + static bool IsCJKIdeographOrSymbol(UChar32 c) { + // Below U+02C7 is likely a common case. + return c < 0x2C7 ? false : IsCJKIdeographOrSymbolSlow(c); + } static bool IsCJKIdeographOrSymbolBase(UChar32 c) { return IsCJKIdeographOrSymbol(c) && !(U_GET_GC_MASK(c) & (U_GC_M_MASK | U_GC_LM_MASK | U_GC_SK_MASK)); @@ -172,6 +175,9 @@ static String NormalizeSpaces(const UChar*, unsigned length); static bool IsCommonOrInheritedScript(UChar32); + + private: + static bool IsCJKIdeographOrSymbolSlow(UChar32); }; } // namespace blink
diff --git a/third_party/WebKit/Source/platform/text/CharacterPropertyDataGenerator.h b/third_party/WebKit/Source/platform/text/CharacterPropertyDataGenerator.h index ff8b206..b2d7bc22 100644 --- a/third_party/WebKit/Source/platform/text/CharacterPropertyDataGenerator.h +++ b/third_party/WebKit/Source/platform/text/CharacterPropertyDataGenerator.h
@@ -47,13 +47,10 @@ 0x4E00, 0x9FFF, // CJK Compatibility Ideographs. 0xF900, 0xFAFF, - // CJK Unified Ideographs Extension B. - 0x20000, 0x2A6DF, - // CJK Unified Ideographs Extension C. - // CJK Unified Ideographs Extension D. - 0x2A700, 0x2B81F, + // Unicode Plane 2: Supplementary Ideographic Plane. This plane includes: + // CJK Unified Ideographs Extension B to F. // CJK Compatibility Ideographs Supplement. - 0x2F800, 0x2FA1F, + 0x20000, 0x2FFFF, // cjkSymbolRanges 0x2156, 0x215A, 0x2160, 0x216B, 0x2170, 0x217B, 0x231A, 0x231B, 0x23E9, @@ -80,13 +77,29 @@ 0x3190, 0x31BF, // Enclosed CJK Letters and Months (0x3200 .. 0x32FF). // CJK Compatibility (0x3300 .. 0x33FF). - 0x3200, 0x33FF, 0xF860, 0xF862, + 0x3200, 0x33FF, + // Yijing Hexagram Symbols + 0x4DC0, 0x4DFF, + // http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/JAPANESE.TXT + 0xF860, 0xF862, // CJK Compatibility Forms. // Small Form Variants (for CNS 11643). 0xFE30, 0xFE6F, // Halfwidth and Fullwidth Forms // Usually only used in CJK 0xFF00, 0xFF0C, 0xFF0E, 0xFF1A, 0xFF1F, 0xFFEF, + // Ideographic Symbols and Punctuation + 0x16FE0, 0x16FFF, + // Tangut + 0x17000, 0x187FF, + // Tangut Components + 0x18800, 0x18AFF, + // Kana Supplement + 0x1B000, 0x1B0FF, + // Kana Extended-A + 0x1B100, 0x1B12F, + // Nushu + 0x1B170, 0x1B2FF, // Emoji. 0x1F110, 0x1F129, 0x1F130, 0x1F149, 0x1F150, 0x1F169, 0x1F170, 0x1F189, 0x1F191, 0x1F19A, 0x1F1E6, 0x1F1FF, 0x1F200, 0x1F6FF, @@ -158,6 +171,8 @@ 0x10980, 0x1099F, // Siddham 0x11580, 0x115FF, + // Zanabazar Square + 0x11A00, 0x11AAF, // Egyptian Hieroglyphs 0x13000, 0x1342F, // Anatolian Hieroglyphs @@ -170,6 +185,10 @@ 0x18800, 0x18AFF, // Kana Supplement 0x1B000, 0x1B0FF, + // Kana Extended-A + 0x1B100, 0x1B12F, + // Nushu + 0x1B170, 0x1B2FF, // Byzantine Musical Symbols/Musical Symbols 0x1D000, 0x1D1FF, // Tai Xuan Jing Symbols/Counting Rod Numerals
diff --git a/third_party/WebKit/Source/platform/text/CharacterTest.cpp b/third_party/WebKit/Source/platform/text/CharacterTest.cpp index 55e4c68..7b0e5a1 100644 --- a/third_party/WebKit/Source/platform/text/CharacterTest.cpp +++ b/third_party/WebKit/Source/platform/text/CharacterTest.cpp
@@ -34,21 +34,30 @@ static void TestSpecificUChar32RangeIdeograph(UChar32 range_start, UChar32 range_end, - bool before = true) { - if (before) - EXPECT_FALSE(Character::IsCJKIdeographOrSymbol(range_start - 1)); - EXPECT_TRUE(Character::IsCJKIdeographOrSymbol(range_start)); - EXPECT_TRUE(Character::IsCJKIdeographOrSymbol( - (UChar32)((uint64_t)range_start + (uint64_t)range_end) / 2)); - EXPECT_TRUE(Character::IsCJKIdeographOrSymbol(range_end)); - EXPECT_FALSE(Character::IsCJKIdeographOrSymbol(range_end + 1)); + bool before = true, + bool after = true) { + if (before) { + EXPECT_FALSE(Character::IsCJKIdeographOrSymbol(range_start - 1)) + << std::hex << (range_start - 1); + } + EXPECT_TRUE(Character::IsCJKIdeographOrSymbol(range_start)) + << std::hex << range_start; + UChar32 mid = static_cast<UChar32>( + (static_cast<uint64_t>(range_start) + range_end) / 2); + EXPECT_TRUE(Character::IsCJKIdeographOrSymbol(mid)) << std::hex << mid; + EXPECT_TRUE(Character::IsCJKIdeographOrSymbol(range_end)) + << std::hex << range_end; + if (after) { + EXPECT_FALSE(Character::IsCJKIdeographOrSymbol(range_end + 1)) + << std::hex << (range_end + 1); + } } TEST(CharacterTest, TestIsCJKIdeograph) { // The basic CJK Unified Ideographs block. - TestSpecificUChar32RangeIdeograph(0x4E00, 0x9FFF); + TestSpecificUChar32RangeIdeograph(0x4E00, 0x9FFF, false); // CJK Unified Ideographs Extension A. - TestSpecificUChar32RangeIdeograph(0x3400, 0x4DBF, false); + TestSpecificUChar32RangeIdeograph(0x3400, 0x4DBF, false, false); // CJK Unified Ideographs Extension A and Kangxi Radicals. TestSpecificUChar32RangeIdeograph(0x2E80, 0x2FDF); // CJK Strokes. @@ -56,12 +65,12 @@ // CJK Compatibility Ideographs. TestSpecificUChar32RangeIdeograph(0xF900, 0xFAFF); // CJK Unified Ideographs Extension B. - TestSpecificUChar32RangeIdeograph(0x20000, 0x2A6DF); + TestSpecificUChar32RangeIdeograph(0x20000, 0x2A6DF, true, false); // CJK Unified Ideographs Extension C. // CJK Unified Ideographs Extension D. - TestSpecificUChar32RangeIdeograph(0x2A700, 0x2B81F); + TestSpecificUChar32RangeIdeograph(0x2A700, 0x2B81F, false, false); // CJK Compatibility Ideographs Supplement. - TestSpecificUChar32RangeIdeograph(0x2F800, 0x2FA1F); + TestSpecificUChar32RangeIdeograph(0x2F800, 0x2FA1F, false, false); } static void TestSpecificUChar32RangeIdeographSymbol(UChar32 range_start, @@ -218,6 +227,23 @@ TestSpecificUChar32RangeIdeographSymbol(0x1F1E6, 0x1F6FF); } +TEST(CharacterTest, CanTextDecorationSkipInk) { + // ASCII + EXPECT_TRUE(Character::CanTextDecorationSkipInk('a')); + // Hangul Jamo + EXPECT_FALSE(Character::CanTextDecorationSkipInk(0x1100)); + // Hiragana + EXPECT_FALSE(Character::CanTextDecorationSkipInk(0x3041)); + // Bopomofo + EXPECT_FALSE(Character::CanTextDecorationSkipInk(0x31A0)); + // The basic CJK Unified Ideographs block + EXPECT_FALSE(Character::CanTextDecorationSkipInk(0x4E01)); + // Hangul Syllables + EXPECT_FALSE(Character::CanTextDecorationSkipInk(0xAC00)); + // Plane 2 / CJK Ideograph Extension B + EXPECT_FALSE(Character::CanTextDecorationSkipInk(0x20000)); +} + TEST(CharacterTest, TestEmojiTextDefault) { // Text-default emoji, i.e. // Emoji=Yes and EmojiPresentation=No
diff --git a/third_party/WebKit/Tools/Scripts/audit-non-blink-usage.py b/third_party/WebKit/Tools/Scripts/audit-non-blink-usage.py index c2c240a..3e4ce46 100755 --- a/third_party/WebKit/Tools/Scripts/audit-non-blink-usage.py +++ b/third_party/WebKit/Tools/Scripts/audit-non-blink-usage.py
@@ -34,6 +34,7 @@ 'base::Location', 'base::MakeRefCounted', 'base::Optional', + 'base::RunLoop', 'base::SingleThreadTaskRunner', 'base::UnguessableToken', 'base::WeakPtr', @@ -46,6 +47,7 @@ # //base/callback.h is allowed, but you need to use WTF::Bind or # WTF::BindRepeating to create callbacks in Blink. + 'base::BarrierClosure', 'base::OnceCallback', 'base::OnceClosure', 'base::RepeatingCallback',
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/monorail.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/monorail.py index d77786f8..3481159 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/monorail.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/monorail.py
@@ -94,7 +94,7 @@ # TODO(robertma): Mock googleapiclient and oauth2client to test this class. _DISCOVERY_URL = ( - 'https://monorail-staging.appspot.com/_ah/api/discovery/v1/apis/' + 'https://monorail-prod.appspot.com/_ah/api/discovery/v1/apis/' '{api}/{apiVersion}/rest') def __init__(self, service_account_key_json=None):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py index 7d75a0a7..c74d50f 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py
@@ -28,7 +28,6 @@ from webkitpy.w3c.directory_owners_extractor import DirectoryOwnersExtractor from webkitpy.w3c.import_notifier import ImportNotifier from webkitpy.w3c.local_wpt import LocalWPT -from webkitpy.w3c.monorail import MonorailAPI, MonorailIssue from webkitpy.w3c.test_copier import TestCopier from webkitpy.w3c.wpt_expectations_updater import WPTExpectationsUpdater from webkitpy.w3c.wpt_github import WPTGitHub @@ -84,18 +83,6 @@ # Print out the full output when executive.run_command fails. self.host.executive.error_output_limit = None - # One-off testing-only code. To be removed (reverted) afterwards. - # ==================== - try: - monorail_issue = MonorailIssue.new_chromium_issue( - 'Test bug filed by wpt-import automatically', description='This is a test', - cc=['robertma@chromium.org'], components=['Blink>Infra']) - monorail_api = MonorailAPI(options.monorail_auth_json) - monorail_api.insert_issue(monorail_issue) - except Exception as e: # pylint:disable=broad-except - _log.error('Failed to create an issue: %s', str(e)) - # ==================== - if not self.checkout_is_okay(): return 1
diff --git a/third_party/WebKit/public/BUILD.gn b/third_party/WebKit/public/BUILD.gn index ec85219..b7a970a 100644 --- a/third_party/WebKit/public/BUILD.gn +++ b/third_party/WebKit/public/BUILD.gn
@@ -439,7 +439,6 @@ "platform/modules/serviceworker/WebServiceWorkerClientsClaimCallbacks.h", "platform/modules/serviceworker/WebServiceWorkerClientsInfo.h", "platform/modules/serviceworker/WebServiceWorkerError.h", - "platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h", "platform/modules/serviceworker/WebServiceWorkerNetworkProvider.h", "platform/modules/serviceworker/WebServiceWorkerProvider.h", "platform/modules/serviceworker/WebServiceWorkerProviderClient.h", @@ -460,7 +459,7 @@ "platform/scheduler/renderer_process_type.h", "web/WebAXEnums.h", "web/WebAXObject.h", - "web/WebActiveWheelFlingParameters.h", + "web/WebActiveFlingParameters.h", "web/WebApplyConstraintsRequest.h", "web/WebArrayBuffer.h", "web/WebArrayBufferConverter.h",
diff --git a/third_party/WebKit/public/platform/WebGestureCurve.h b/third_party/WebKit/public/platform/WebGestureCurve.h index 758b2dc4..2c9332a 100644 --- a/third_party/WebKit/public/platform/WebGestureCurve.h +++ b/third_party/WebKit/public/platform/WebGestureCurve.h
@@ -25,9 +25,11 @@ #ifndef WebGestureCurve_h #define WebGestureCurve_h -namespace blink { +#include "third_party/WebKit/public/platform/WebFloatSize.h" +#include "third_party/WebKit/public/platform/WebGestureCurveTarget.h" +#include "ui/gfx/geometry/vector2d_f.h" -class WebGestureCurveTarget; +namespace blink { // Abstract interface for curves used by ActivePlatformGestureAnimation. A // WebGestureCurve defines the animation parameters as a function of time @@ -38,7 +40,30 @@ virtual ~WebGestureCurve() {} // Returns false if curve has finished and can no longer be applied. - virtual bool Apply(double time, WebGestureCurveTarget*) = 0; + // TODO(sahel): This will get removed once touchscreen and autoscroll flings + // are handled on browser side (crbug.com/249063). + bool AdvanceAndApplyToTarget(double time, WebGestureCurveTarget* target) { + gfx::Vector2dF velocity, delta; + bool still_active = Advance(time, velocity, delta); + + // As successive timestamps can be arbitrarily close (but monotonic!), don't + // assume that a zero delta means the curve has terminated. + if (delta.IsZero()) + return still_active; + + // scrollBy() could delete this curve if the animation is over, so don't + // touch any member variables after making that call. + bool did_scroll = + target->ScrollBy(blink::WebFloatSize(delta.x(), delta.y()), + blink::WebFloatSize(velocity.x(), velocity.y())); + return did_scroll && still_active; + } + + // Returns false if curve has finished and can no longer advance. + // This function is used for browser side fling. + virtual bool Advance(double time, + gfx::Vector2dF& out_current_velocity, + gfx::Vector2dF& out_delta_to_scroll) = 0; }; } // namespace blink
diff --git a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h b/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h deleted file mode 100644 index fc46584..0000000 --- a/third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerInstalledScriptsManager.h +++ /dev/null
@@ -1,97 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef WebServiceWorkerInstalledScriptsManager_h -#define WebServiceWorkerInstalledScriptsManager_h - -#include "public/platform/WebString.h" -#include "public/platform/WebURL.h" -#include "public/platform/WebVector.h" - -#if INSIDE_BLINK -#include <memory> -#include "platform/network/HTTPHeaderMap.h" -#endif // INSIDE_BLINK - -namespace blink { - -// WebServiceWorkerInstalledScriptsManager provides installed main script and -// imported scripts to the service worker thread. This is used by multiple -// threads, so implementation needs to be thread safe. -class WebServiceWorkerInstalledScriptsManager { - public: - using BytesChunk = WebVector<char>; - // Container of a script. All the fields of this class need to be - // cross-thread-transfer-safe. - class BLINK_PLATFORM_EXPORT RawScriptData { - public: - static std::unique_ptr<RawScriptData> Create( - WebString encoding, - WebVector<BytesChunk> script_text, - WebVector<BytesChunk> meta_data); - static std::unique_ptr<RawScriptData> CreateInvalidInstance(); - - // Implementation of the destructor should be in the Blink side because only - // Blink can know all of members. - ~RawScriptData(); - - void AddHeader(const WebString& key, const WebString& value); - - // Returns false if it fails to receive the script from the browser. - bool IsValid() const { return is_valid_; } - // The encoding of the script text. - const WebString& Encoding() const { - DCHECK(is_valid_); - return encoding_; - } - // An array of raw byte chunks of the script text. - const WebVector<BytesChunk>& ScriptTextChunks() const { - DCHECK(is_valid_); - return script_text_; - } - // An array of raw byte chunks of the scripts's meta data from the script's - // V8 code cache. - const WebVector<BytesChunk>& MetaDataChunks() const { - DCHECK(is_valid_); - return meta_data_; - } - -#if INSIDE_BLINK - // The HTTP headers of the script. - std::unique_ptr<CrossThreadHTTPHeaderMapData> TakeHeaders() { - DCHECK(is_valid_); - return std::move(headers_); - } -#endif // INSIDE_BLINK - - private: - // This instance must be created on the Blink side because only Blink can - // know the exact size of this instance. - RawScriptData(WebString encoding, - WebVector<BytesChunk> script_text, - WebVector<BytesChunk> meta_data, - bool is_valid); - const bool is_valid_; - WebString encoding_; - WebVector<BytesChunk> script_text_; - WebVector<BytesChunk> meta_data_; -#if INSIDE_BLINK - std::unique_ptr<CrossThreadHTTPHeaderMapData> headers_; -#endif // INSIDE_BLINK - }; - - virtual ~WebServiceWorkerInstalledScriptsManager() = default; - - // Called on the main or worker thread. - virtual bool IsScriptInstalled(const blink::WebURL& script_url) const = 0; - // Returns the script data for |script_url|. When an error happened during - // receiving the script, returns an invalid instance. - // Called on the worker thread. - virtual std::unique_ptr<RawScriptData> GetRawScriptData( - const WebURL& script_url) = 0; -}; - -} // namespace blink - -#endif // WebServiceWorkerInstalledScriptsManager_h
diff --git a/third_party/WebKit/public/web/WebActiveWheelFlingParameters.h b/third_party/WebKit/public/web/WebActiveFlingParameters.h similarity index 92% rename from third_party/WebKit/public/web/WebActiveWheelFlingParameters.h rename to third_party/WebKit/public/web/WebActiveFlingParameters.h index 12796bf..baed325 100644 --- a/third_party/WebKit/public/web/WebActiveWheelFlingParameters.h +++ b/third_party/WebKit/public/web/WebActiveFlingParameters.h
@@ -23,8 +23,8 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WebActiveWheelFlingParameters_h -#define WebActiveWheelFlingParameters_h +#ifndef WebActiveFlingParameters_h +#define WebActiveFlingParameters_h #include "public/platform/WebCommon.h" #include "public/platform/WebFloatPoint.h" @@ -34,7 +34,7 @@ namespace blink { -struct WebActiveWheelFlingParameters { +struct WebActiveFlingParameters { WebFloatPoint delta; WebPoint point; WebPoint global_point; @@ -43,9 +43,9 @@ WebSize cumulative_scroll; double start_time; - WebActiveWheelFlingParameters() + WebActiveFlingParameters() : modifiers(0), source_device(kWebGestureDeviceTouchpad), start_time(0) {} }; -} +} // namespace blink #endif
diff --git a/third_party/WebKit/public/web/WebDevToolsAgentClient.h b/third_party/WebKit/public/web/WebDevToolsAgentClient.h index 3dade51..6dd34fb 100644 --- a/third_party/WebKit/public/web/WebDevToolsAgentClient.h +++ b/third_party/WebKit/public/web/WebDevToolsAgentClient.h
@@ -66,11 +66,6 @@ return false; } - virtual void EnableTracing(const WebString& category_filter) {} - virtual void DisableTracing() {} - - virtual void SetCPUThrottlingRate(double rate) {} - protected: ~WebDevToolsAgentClient() {} };
diff --git a/third_party/WebKit/public/web/WebEmbeddedWorker.h b/third_party/WebKit/public/web/WebEmbeddedWorker.h index 26c74050..df2e84c 100644 --- a/third_party/WebKit/public/web/WebEmbeddedWorker.h +++ b/third_party/WebKit/public/web/WebEmbeddedWorker.h
@@ -35,16 +35,27 @@ #include "mojo/public/cpp/system/message_pipe.h" #include "public/platform/WebCommon.h" +#include "public/platform/WebVector.h" namespace blink { class WebContentSettingsClient; class WebServiceWorkerContextClient; -class WebServiceWorkerInstalledScriptsManager; class WebString; +class WebURL; struct WebConsoleMessage; struct WebEmbeddedWorkerStartData; +// As we're on the border line between non-Blink and Blink variants, we need +// to use mojo::ScopedMessagePipeHandle to pass Mojo types. +struct WebServiceWorkerInstalledScriptsManagerParams { + WebVector<WebURL> installed_scripts_urls; + // A handle for mojom::blink::ServiceWorkerInstalledScriptsManagerRequest. + mojo::ScopedMessagePipeHandle manager_request; + // A handle for mojom::blink::ServiceWorkerInstalledScriptsManagerHostPtrInfo. + mojo::ScopedMessagePipeHandle manager_host_ptr; +}; + // An interface to start and terminate an embedded worker. // All methods of this class must be called on the main thread. class BLINK_EXPORT WebEmbeddedWorker { @@ -55,8 +66,10 @@ // WorkerGlobalScope. static std::unique_ptr<WebEmbeddedWorker> Create( std::unique_ptr<WebServiceWorkerContextClient>, - std::unique_ptr<WebServiceWorkerInstalledScriptsManager>, + std::unique_ptr<WebServiceWorkerInstalledScriptsManagerParams>, + // A handle for mojom::blink::WorkerContentSettingsProxyPtrInfo. mojo::ScopedMessagePipeHandle content_settings_handle, + // A handle for service_manager::mojom::blink::InterfaceProviderPtrInfo. mojo::ScopedMessagePipeHandle interface_provider); virtual ~WebEmbeddedWorker() {}
diff --git a/third_party/WebKit/public/web/WebFrameWidget.h b/third_party/WebKit/public/web/WebFrameWidget.h index be1157ca..a19938c 100644 --- a/third_party/WebKit/public/web/WebFrameWidget.h +++ b/third_party/WebKit/public/web/WebFrameWidget.h
@@ -42,7 +42,6 @@ class WebLocalFrame; class WebInputMethodController; class WebWidgetClient; -struct WebActiveWheelFlingParameters; struct WebFloatPoint; class WebFrameWidget : public WebWidget { @@ -132,12 +131,6 @@ virtual void UpdateRenderThrottlingStatus(bool is_throttled, bool subtree_throttled) {} - // Called to inform the WebFrameWidget that a wheel fling animation was - // started externally (for instance by the compositor) but must be completed - // by the WebFrameWidget. - virtual void TransferActiveWheelFlingAnimation( - const WebActiveWheelFlingParameters&) = 0; - // Returns the currently focused WebLocalFrame (if any) inside this // WebFrameWidget. That is a WebLocalFrame which is focused and shares the // same LocalRoot() as this WebFrameWidget's LocalRoot().
diff --git a/third_party/closure_compiler/externs/developer_private.js b/third_party/closure_compiler/externs/developer_private.js index ab53fc0a..f7f914f 100644 --- a/third_party/closure_compiler/externs/developer_private.js +++ b/third_party/closure_compiler/externs/developer_private.js
@@ -606,6 +606,14 @@ chrome.developerPrivate.getExtensionInfo = function(id, callback) {}; /** + * Returns the size of a particular extension on disk (already formatted). + * @param {string} id The id of the extension. + * @param {function(string):void} callback Called with the result. + * @see https://developer.chrome.com/extensions/developerPrivate#method-getExtensionSize + */ +chrome.developerPrivate.getExtensionSize = function(id, callback) {}; + +/** * Returns information of all the extensions and apps installed. * @param {boolean} includeDisabled include disabled items. * @param {boolean} includeTerminated include terminated items.
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium index fe8395a..ce4a7b9 100644 --- a/third_party/crashpad/README.chromium +++ b/third_party/crashpad/README.chromium
@@ -2,7 +2,7 @@ Short Name: crashpad URL: https://crashpad.chromium.org/ Version: unknown -Revision: 0924e567514fc577e725b56cd602808467b317a9 +Revision: 10ff56eee5da29d14b86818b88a93d3e96b4bacd License: Apache 2.0 License File: crashpad/LICENSE Security Critical: yes
diff --git a/third_party/crashpad/crashpad/.gitignore b/third_party/crashpad/crashpad/.gitignore index 4180696..e6daaab 100644 --- a/third_party/crashpad/crashpad/.gitignore +++ b/third_party/crashpad/crashpad/.gitignore
@@ -12,6 +12,7 @@ /out /third_party/fuchsia/.cipd /third_party/fuchsia/clang +/third_party/fuchsia/qemu /third_party/fuchsia/sdk /third_party/gtest/gtest /third_party/gyp/gyp
diff --git a/third_party/crashpad/crashpad/DEPS b/third_party/crashpad/crashpad/DEPS index 79fb643..c59ff43 100644 --- a/third_party/crashpad/crashpad/DEPS +++ b/third_party/crashpad/crashpad/DEPS
@@ -28,7 +28,7 @@ '5e2b3ddde7cda5eb6bc09a5546a76b00e49d888f', 'crashpad/third_party/mini_chromium/mini_chromium': Var('chromium_git') + '/chromium/mini_chromium@' + - 'a12ed4a613a7df900059c8a7885acdad550a5319', + '20182dd263312db9fad52042fc92c33331ec6904', 'crashpad/third_party/zlib/zlib': Var('chromium_git') + '/chromium/src/third_party/zlib@' + '13dc246a58e4b72104d35f9b1809af95221ebda7', @@ -146,6 +146,36 @@ ], }, { + # Same rationale for using "install" rather than "ensure" as for clang + # packages. https://crbug.com/789364. + 'name': 'fuchsia_qemu_mac', + 'pattern': '.', + 'condition': 'checkout_fuchsia and host_os == "mac"', + 'action': [ + 'cipd', + 'install', + 'fuchsia/qemu/mac-amd64', + 'latest', + '-root', 'crashpad/third_party/fuchsia/qemu/mac-amd64', + '-log-level', 'info', + ], + }, + { + # Same rationale for using "install" rather than "ensure" as for clang + # packages. https://crbug.com/789364. + 'name': 'fuchsia_qemu_linux', + 'pattern': '.', + 'condition': 'checkout_fuchsia and host_os == "linux"', + 'action': [ + 'cipd', + 'install', + 'fuchsia/qemu/linux-amd64', + 'latest', + '-root', 'crashpad/third_party/fuchsia/qemu/linux-amd64', + '-log-level', 'info', + ], + }, + { # The SDK is keyed to the host system because it contains build tools. # Currently, linux-amd64 is the only SDK published (see # https://chrome-infra-packages.appspot.com/#/?path=fuchsia/sdk). As long as
diff --git a/third_party/crashpad/crashpad/build/run_fuchsia_qemu.py b/third_party/crashpad/crashpad/build/run_fuchsia_qemu.py new file mode 100755 index 0000000..e3f4efc --- /dev/null +++ b/third_party/crashpad/crashpad/build/run_fuchsia_qemu.py
@@ -0,0 +1,119 @@ +#!/usr/bin/env python + +# Copyright 2017 The Crashpad Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Helper script to [re]start or stop a helper Fuchsia QEMU instance to be used +for running tests without a device. +""" + +from __future__ import print_function + +import getpass +import os +import random +import signal +import subprocess +import sys +import tempfile + +try: + from subprocess import DEVNULL +except ImportError: + DEVNULL = open(os.devnull, 'r+b') + +CRASHPAD_ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), + os.pardir) + + +def _Stop(pid_file): + if os.path.isfile(pid_file): + with open(pid_file, 'rb') as f: + pid = int(f.read().strip()) + try: + os.kill(pid, signal.SIGTERM) + except: + print('Unable to kill pid %d, continuing' % pid, file=sys.stderr) + os.unlink(pid_file) + + +def _CheckForTun(): + """Check for networking. TODO(scottmg): Currently, this is Linux-specific. + """ + returncode = subprocess.call( + ['tunctl', '-b', '-u', getpass.getuser(), '-t', 'qemu'], + stdout=DEVNULL, stderr=DEVNULL) + if returncode != 0: + print('To use QEMU with networking on Linux, configure TUN/TAP. See:', + file=sys.stderr) + print(' https://fuchsia.googlesource.com/magenta/+/HEAD/docs/qemu.md#enabling-networking-under-qemu-x86_64-only', + file=sys.stderr) + return 2 + return 0 + + +def _Start(pid_file): + tun_result = _CheckForTun() + if tun_result != 0: + return tun_result + + arch = 'mac-amd64' if sys.platform == 'darwin' else 'linux-amd64' + fuchsia_dir = os.path.join(CRASHPAD_ROOT, 'third_party', 'fuchsia') + qemu_path = os.path.join(fuchsia_dir, 'qemu', arch, 'bin', + 'qemu-system-x86_64') + kernel_data_dir = os.path.join(fuchsia_dir, 'sdk', arch, 'target', 'x86_64') + kernel_path = os.path.join(kernel_data_dir, 'zircon.bin') + initrd_path = os.path.join(kernel_data_dir, 'bootdata.bin') + + mac_tail = ':'.join('%02x' % random.randint(0, 255) for x in range(3)) + + # These arguments are from the Fuchsia repo in zircon/scripts/run-zircon. + popen = subprocess.Popen([ + qemu_path, + '-m', '2048', + '-nographic', + '-kernel', kernel_path, + '-initrd', initrd_path, + '-smp', '4', + '-serial', 'stdio', + '-monitor', 'none', + '-machine', 'q35', + '-cpu', 'host,migratable=no', + '-enable-kvm', + '-netdev', 'type=tap,ifname=qemu,script=no,downscript=no,id=net0', + '-device', 'e1000,netdev=net0,mac=52:54:00:' + mac_tail, + '-append', 'TERM=dumb', + ], stdin=DEVNULL, stdout=DEVNULL, stderr=DEVNULL) + + with open(pid_file, 'wb') as f: + f.write('%d\n' % popen.pid) + + +def main(args): + if len(args) != 1 or args[0] not in ('start', 'stop'): + print('usage: run_fuchsia_qemu.py start|stop', file=sys.stderr) + return 1 + + command = args[0] + + pid_file = os.path.join(tempfile.gettempdir(), 'crashpad_fuchsia_qemu_pid') + _Stop(pid_file) + if command == 'start': + _Start(pid_file) + + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:]))
diff --git a/third_party/crashpad/crashpad/util/file/file_io_posix.cc b/third_party/crashpad/crashpad/util/file/file_io_posix.cc index b2afdc0..2993279 100644 --- a/third_party/crashpad/crashpad/util/file/file_io_posix.cc +++ b/third_party/crashpad/crashpad/util/file/file_io_posix.cc
@@ -25,6 +25,7 @@ #include "base/files/file_path.h" #include "base/logging.h" #include "base/posix/eintr_wrapper.h" +#include "build/build_config.h" namespace crashpad { @@ -66,7 +67,12 @@ const base::FilePath& path, FileWriteMode mode, FilePermissions permissions) { +#if defined(OS_FUCHSIA) + // O_NOCTTY is invalid on Fuchsia, and O_CLOEXEC isn't necessary. + int flags = 0; +#else int flags = O_NOCTTY | O_CLOEXEC; +#endif DCHECK(rdwr_or_wronly & (O_RDWR | O_WRONLY)); DCHECK_EQ(rdwr_or_wronly & ~(O_RDWR | O_WRONLY), 0);
diff --git a/third_party/crashpad/crashpad/util/file/filesystem_test.cc b/third_party/crashpad/crashpad/util/file/filesystem_test.cc index 28d2d88a..3430c3f 100644 --- a/third_party/crashpad/crashpad/util/file/filesystem_test.cc +++ b/third_party/crashpad/crashpad/util/file/filesystem_test.cc
@@ -373,7 +373,6 @@ EXPECT_FALSE(LoggingRemoveFile(base::FilePath())); ScopedTempDir temp_dir; - EXPECT_FALSE(LoggingRemoveFile(temp_dir.path())); base::FilePath file(temp_dir.path().Append(FILE_PATH_LITERAL("file"))); EXPECT_FALSE(LoggingRemoveFile(file)); @@ -384,7 +383,6 @@ base::FilePath dir(temp_dir.path().Append(FILE_PATH_LITERAL("dir"))); ASSERT_TRUE( LoggingCreateDirectory(dir, FilePermissions::kWorldReadable, false)); - EXPECT_FALSE(LoggingRemoveFile(dir)); EXPECT_TRUE(LoggingRemoveFile(file)); EXPECT_FALSE(PathExists(file)); @@ -433,8 +431,16 @@ EXPECT_FALSE(LoggingRemoveDirectory(file)); ASSERT_TRUE(CreateFile(file)); +#if !defined(OS_FUCHSIA) + // The current implementation of Fuchsia's rmdir() simply calls unlink(), and + // unlink() works on all FS objects. This is incorrect as + // http://pubs.opengroup.org/onlinepubs/9699919799/functions/rmdir.html says + // "The directory shall be removed only if it is an empty directory." and "If + // the directory is not an empty directory, rmdir() shall fail and set errno + // to [EEXIST] or [ENOTEMPTY]." Upstream bug: US-400. EXPECT_FALSE(LoggingRemoveDirectory(file)); EXPECT_FALSE(LoggingRemoveDirectory(dir)); +#endif ASSERT_TRUE(LoggingRemoveFile(file)); EXPECT_TRUE(LoggingRemoveDirectory(dir));
diff --git a/third_party/crashpad/crashpad/util/misc/metrics.cc b/third_party/crashpad/crashpad/util/misc/metrics.cc index 30de6b9..f4fb588 100644 --- a/third_party/crashpad/crashpad/util/misc/metrics.cc +++ b/third_party/crashpad/crashpad/util/misc/metrics.cc
@@ -14,8 +14,8 @@ #include "util/misc/metrics.h" +#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" -#include "base/metrics/sparse_histogram.h" #include "build/build_config.h" #if defined(OS_MACOSX) @@ -91,8 +91,8 @@ // static void Metrics::ExceptionCode(uint32_t exception_code) { - UMA_HISTOGRAM_SPARSE_SLOWLY("Crashpad.ExceptionCode." METRICS_OS_NAME, - static_cast<int32_t>(exception_code)); + base::UmaHistogramSparse("Crashpad.ExceptionCode." METRICS_OS_NAME, + static_cast<int32_t>(exception_code)); } // static @@ -109,7 +109,7 @@ // static void Metrics::HandlerCrashed(uint32_t exception_code) { - UMA_HISTOGRAM_SPARSE_SLOWLY( + base::UmaHistogramSparse( "Crashpad.HandlerCrash.ExceptionCode." METRICS_OS_NAME, static_cast<int32_t>(exception_code)); }
diff --git a/third_party/polymer/v1_0/bower.json b/third_party/polymer/v1_0/bower.json index a642891..2813dab 100644 --- a/third_party/polymer/v1_0/bower.json +++ b/third_party/polymer/v1_0/bower.json
@@ -53,7 +53,7 @@ "paper-tabs": "PolymerElements/paper-tabs#1.6.2", "paper-toggle-button": "PolymerElements/paper-toggle-button#1.3.0", "paper-tooltip": "PolymerElements/paper-tooltip#1.1.4", - "polymer": "Polymer/polymer#1.9.1", + "polymer": "Polymer/polymer#1.11.2", "web-animations-js": "web-animations/web-animations-js#2.2.2" } }
diff --git a/third_party/polymer/v1_0/components-chromium/polymer/bower.json b/third_party/polymer/v1_0/components-chromium/polymer/bower.json index c49ba078..1ad66dc 100644 --- a/third_party/polymer/v1_0/components-chromium/polymer/bower.json +++ b/third_party/polymer/v1_0/components-chromium/polymer/bower.json
@@ -1,6 +1,6 @@ { "name": "polymer", - "version": "1.9.1", + "version": "1.11.2", "main": [ "polymer.html", "polymer-mini.html", @@ -25,7 +25,7 @@ "url": "https://github.com/Polymer/polymer.git" }, "dependencies": { - "webcomponentsjs": "^0.7.24" + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.7.24" }, "devDependencies": { "web-component-tester": "*",
diff --git a/third_party/polymer/v1_0/components-chromium/polymer/polymer-extracted.js b/third_party/polymer/v1_0/components-chromium/polymer/polymer-extracted.js index 8558fbdc..1fcacd7 100644 --- a/third_party/polymer/v1_0/components-chromium/polymer/polymer-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/polymer/polymer-extracted.js
@@ -540,6 +540,9 @@ return false; } }(); +function isMouseEvent(name) { +return MOUSE_EVENTS.indexOf(name) > -1; +} var SUPPORTS_PASSIVE = false; (function () { try { @@ -553,6 +556,14 @@ } catch (e) { } }()); +function PASSIVE_TOUCH(eventName) { +if (isMouseEvent(eventName) || eventName === 'touchend') { +return; +} +if (HAS_NATIVE_TA && SUPPORTS_PASSIVE && Polymer.Settings.passiveTouchGestures) { +return { passive: true }; +} +} var IS_TOUCH_ONLY = navigator.userAgent.match(/iP(?:[oa]d|hone)|Android/); var mouseCanceller = function (mouseEvent) { var sc = mouseEvent.sourceCapabilities; @@ -596,7 +607,7 @@ } function hasLeftMouseButton(ev) { var type = ev.type; -if (MOUSE_EVENTS.indexOf(type) === -1) { +if (!isMouseEvent(type)) { return false; } if (type === 'mousemove') { @@ -773,7 +784,7 @@ } for (var i = 0, dep, gd; i < deps.length; i++) { dep = deps[i]; -if (IS_TOUCH_ONLY && MOUSE_EVENTS.indexOf(dep) > -1 && dep !== 'click') { +if (IS_TOUCH_ONLY && isMouseEvent(dep) && dep !== 'click') { continue; } gd = gobj[dep]; @@ -781,7 +792,7 @@ gobj[dep] = gd = { _count: 0 }; } if (gd._count === 0) { -node.addEventListener(dep, this.handleNative); +node.addEventListener(dep, this.handleNative, PASSIVE_TOUCH(dep)); } gd[name] = (gd[name] || 0) + 1; gd._count = (gd._count || 0) + 1; @@ -805,7 +816,7 @@ gd[name] = (gd[name] || 1) - 1; gd._count = (gd._count || 1) - 1; if (gd._count === 0) { -node.removeEventListener(dep, this.handleNative); +node.removeEventListener(dep, this.handleNative, PASSIVE_TOUCH(dep)); } } } @@ -2515,6 +2526,8 @@ }();Polymer.StyleUtil = function () { var settings = Polymer.Settings; return { +unscopedStyleImports: new WeakMap(), +SHADY_UNSCOPED_ATTR: 'shady-unscoped', NATIVE_VARIABLES: Polymer.Settings.useNativeCSSProperties, MODULE_STYLES_SELECTOR: 'style, link[rel=import][type~=css], template', INCLUDE_ATTR: 'include', @@ -2622,7 +2635,7 @@ return placeHolder; }, cssFromModules: function (moduleIds, warnIfNotFound) { -var modules = moduleIds.trim().split(' '); +var modules = moduleIds.trim().split(/\s+/); var cssText = ''; for (var i = 0; i < modules.length; i++) { cssText += this.cssFromModule(modules[i], warnIfNotFound); @@ -2657,9 +2670,26 @@ } e = e.__appliedElement || e; e.parentNode.removeChild(e); -cssText += this.resolveCss(e.textContent, element.ownerDocument); +var css = this.resolveCss(e.textContent, element.ownerDocument); +if (!settings.useNativeShadow && e.hasAttribute(this.SHADY_UNSCOPED_ATTR)) { +e.textContent = css; +document.head.insertBefore(e, document.head.firstChild); +} else { +cssText += css; +} } else if (e.import && e.import.body) { -cssText += this.resolveCss(e.import.body.textContent, e.import); +var importCss = this.resolveCss(e.import.body.textContent, e.import); +if (!settings.useNativeShadow && e.hasAttribute(this.SHADY_UNSCOPED_ATTR)) { +if (!this.unscopedStyleImports.has(e.import)) { +this.unscopedStyleImports.set(e.import, true); +var importStyle = document.createElement('style'); +importStyle.setAttribute(this.SHADY_UNSCOPED_ATTR, ''); +importStyle.textContent = importCss; +document.head.insertBefore(importStyle, document.head.firstChild); +} +} else { +cssText += importCss; +} } } } @@ -2813,6 +2843,7 @@ cb = function (rule) { rule.selector = self._slottedToContent(rule.selector); rule.selector = rule.selector.replace(ROOT, ':host > *'); +rule.selector = self._dirShadowTransform(rule.selector); if (callback) { callback(rule); } @@ -2854,8 +2885,31 @@ _transformRule: function (rule, transformer, scope, hostScope) { rule.selector = rule.transformedSelector = this._transformRuleCss(rule, transformer, scope, hostScope); }, +_splitSelectorList: function (selector) { +var parts = []; +var part = ''; +for (var i = 0; i >= 0 && i < selector.length; i++) { +if (selector[i] === '(') { +var end = styleUtil._findMatchingParen(selector, i); +part += selector.slice(i, end + 1); +i = end; +} else if (selector[i] === COMPLEX_SELECTOR_SEP) { +parts.push(part); +part = ''; +} else { +part += selector[i]; +} +} +if (part) { +parts.push(part); +} +if (parts.length === 0) { +parts.push(selector); +} +return parts; +}, _transformRuleCss: function (rule, transformer, scope, hostScope) { -var p$ = rule.selector.split(COMPLEX_SELECTOR_SEP); +var p$ = this._splitSelectorList(rule.selector); if (!styleUtil.isKeyframesSelector(rule)) { for (var i = 0, l = p$.length, p; i < l && (p = p$[i]); i++) { p$[i] = transformer.call(this, p, scope, hostScope); @@ -2863,19 +2917,36 @@ } return p$.join(COMPLEX_SELECTOR_SEP); }, +_ensureScopedDir: function (s) { +var m = s.match(DIR_PAREN); +if (m && m[1] === '' && m[0].length === s.length) { +s = '*' + s; +} +return s; +}, +_additionalDirSelectors: function (dir, after, prefix) { +if (!dir || !after) { +return ''; +} +prefix = prefix || ''; +return COMPLEX_SELECTOR_SEP + prefix + ' ' + dir + ' ' + after; +}, _transformComplexSelector: function (selector, scope, hostScope) { var stop = false; var hostContext = false; +var dir = false; var self = this; selector = selector.trim(); selector = this._slottedToContent(selector); selector = selector.replace(ROOT, ':host > *'); selector = selector.replace(CONTENT_START, HOST + ' $1'); +selector = this._ensureScopedDir(selector); selector = selector.replace(SIMPLE_SELECTOR_SEP, function (m, c, s) { if (!stop) { var info = self._transformCompoundSelector(s, c, scope, hostScope); stop = stop || info.stop; hostContext = hostContext || info.hostContext; +dir = dir || info.dir; c = info.combinator; s = info.value; } else { @@ -2885,14 +2956,28 @@ }); if (hostContext) { selector = selector.replace(HOST_CONTEXT_PAREN, function (m, pre, paren, post) { -return pre + paren + ' ' + hostScope + post + COMPLEX_SELECTOR_SEP + ' ' + pre + hostScope + paren + post; +var replacement = pre + paren + ' ' + hostScope + post + COMPLEX_SELECTOR_SEP + ' ' + pre + hostScope + paren + post; +if (dir) { +replacement += self._additionalDirSelectors(paren, post, hostScope); +} +return replacement; }); } return selector; }, +_transformDir: function (s) { +s = s.replace(HOST_DIR, HOST_DIR_REPLACE); +s = s.replace(DIR_PAREN, DIR_REPLACE); +return s; +}, _transformCompoundSelector: function (selector, combinator, scope, hostScope) { var jumpIndex = selector.search(SCOPE_JUMP); var hostContext = false; +var dir = false; +if (selector.match(DIR_PAREN)) { +selector = this._transformDir(selector); +dir = true; +} if (selector.indexOf(HOST_CONTEXT) >= 0) { hostContext = true; } else if (selector.indexOf(HOST) >= 0) { @@ -2912,7 +2997,8 @@ value: selector, combinator: combinator, stop: stop, -hostContext: hostContext +hostContext: hostContext, +dir: dir }; }, _transformSimpleSelector: function (selector, scope) { @@ -2949,13 +3035,32 @@ }, normalizeRootSelector: function (rule) { rule.selector = rule.selector.replace(ROOT, 'html'); +var parts = this._splitSelectorList(rule.selector); +parts = parts.filter(function (part) { +return !part.match(HOST_OR_HOST_GT_STAR); +}); +rule.selector = parts.join(COMPLEX_SELECTOR_SEP); }, _transformDocumentSelector: function (selector) { -return selector.match(SCOPE_JUMP) ? this._transformComplexSelector(selector, SCOPE_DOC_SELECTOR) : this._transformSimpleSelector(selector.trim(), SCOPE_DOC_SELECTOR); +return this._transformComplexSelector(selector, SCOPE_DOC_SELECTOR); }, _slottedToContent: function (cssText) { return cssText.replace(SLOTTED_PAREN, CONTENT + '> $1'); }, +_dirShadowTransform: function (selector) { +if (!selector.match(/:dir\(/)) { +return selector; +} +return this._splitSelectorList(selector).map(function (s) { +s = this._ensureScopedDir(s); +s = this._transformDir(s); +var m = HOST_CONTEXT_PAREN.exec(s); +if (m) { +s += this._additionalDirSelectors(m[2], m[3], ''); +} +return s; +}, this).join(COMPLEX_SELECTOR_SEP); +}, SCOPE_NAME: 'style-scope' }; var SCOPE_NAME = api.SCOPE_NAME; @@ -2978,6 +3083,11 @@ var CONTENT_START = new RegExp('^(' + CONTENT + ')'); var SELECTOR_NO_MATCH = 'should_not_match'; var SLOTTED_PAREN = /(?:::slotted)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/g; +var HOST_OR_HOST_GT_STAR = /:host(?:\s*>\s*\*)?/; +var DIR_PAREN = /(.*):dir\((ltr|rtl)\)/; +var DIR_REPLACE = ':host-context([dir="$2"]) $1'; +var HOST_DIR = /:host\(:dir\((rtl|ltr)\)\)/g; +var HOST_DIR_REPLACE = ':host-context([dir="$1"])'; return api; }();Polymer.StyleExtends = function () { var styleUtil = Polymer.StyleUtil; @@ -3658,13 +3768,18 @@ rule.transformedSelector = rule.transformedSelector || rule.selector; rule.selector = rule.transformedSelector.replace(rule.keyframesName, rule.transformedKeyframesName); }, +_hasDirOrHostContext: function (parsedSelector) { +return /:host-context|:dir/.test(parsedSelector); +}, _scopeSelector: function (rule, hostRx, hostSelector, viaAttr, scopeId) { rule.transformedSelector = rule.transformedSelector || rule.selector; var selector = rule.transformedSelector; -var scope = viaAttr ? '[' + styleTransformer.SCOPE_NAME + '~=' + scopeId + ']' : '.' + scopeId; +var scope = styleTransformer._calcElementScope(scopeId, viaAttr); +var hostScope = styleTransformer._calcElementScope(hostSelector, viaAttr); var parts = selector.split(','); +var isDirOrHostContextSelector = this._hasDirOrHostContext(rule.parsedSelector); for (var i = 0, l = parts.length, p; i < l && (p = parts[i]); i++) { -parts[i] = p.match(hostRx) ? p.replace(hostSelector, scope) : scope + ' ' + p; +parts[i] = p.match(hostRx) ? p.replace(hostSelector, scope) : isDirOrHostContextSelector ? p.replace(hostScope, scope + ' ' + hostScope) : scope + ' ' + p; } rule.selector = parts.join(','); }, @@ -4114,6 +4229,9 @@ if (this.__appliedElement !== this) { this.__appliedElement.__cssBuild = this.__cssBuild; } +if (this.ownerDocument !== window.document && this.__appliedElement === this) { +document.head.appendChild(this); +} this._tryApply(); }, attached: function () {
diff --git a/third_party/polymer/v1_0/components-chromium/polymer/polymer-micro-extracted.js b/third_party/polymer/v1_0/components-chromium/polymer/polymer-micro-extracted.js index b3e3aa0..9babb83 100644 --- a/third_party/polymer/v1_0/components-chromium/polymer/polymer-micro-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/polymer/polymer-micro-extracted.js
@@ -30,9 +30,10 @@ settings.useNativeCustomElements = !window.CustomElements || window.CustomElements.useNative; settings.useNativeShadow = settings.useShadow && settings.nativeShadow; settings.usePolyfillProto = !settings.useNativeCustomElements && !Object.__proto__; -settings.hasNativeCSSProperties = !navigator.userAgent.match('AppleWebKit/601') && window.CSS && CSS.supports && CSS.supports('box-shadow', '0 0 0 var(--foo)'); +settings.hasNativeCSSProperties = !navigator.userAgent.match(/AppleWebKit\/601|Edge\/15/) && window.CSS && CSS.supports && CSS.supports('box-shadow', '0 0 0 var(--foo)'); settings.useNativeCSSProperties = settings.hasNativeCSSProperties && settings.lazyRegister && settings.useNativeCSSProperties; settings.isIE = navigator.userAgent.match('Trident'); +settings.passiveTouchGestures = settings.passiveTouchGestures || false; return settings; }() };(function () { @@ -782,7 +783,7 @@ return value != null ? value : undefined; } } -});Polymer.version = "1.9.1";Polymer.Base._addFeature({ +});Polymer.version = "1.11.2";Polymer.Base._addFeature({ _registerFeatures: function () { this._prepIs(); this._prepBehaviors();
diff --git a/third_party/polymer/v1_0/components-chromium/polymer/polymer-mini-extracted.js b/third_party/polymer/v1_0/components-chromium/polymer/polymer-mini-extracted.js index 1d21ad1..f92a912 100644 --- a/third_party/polymer/v1_0/components-chromium/polymer/polymer-mini-extracted.js +++ b/third_party/polymer/v1_0/components-chromium/polymer/polymer-mini-extracted.js
@@ -94,6 +94,7 @@ } });(function () { var baseAttachedCallback = Polymer.Base.attachedCallback; +var baseDetachedCallback = Polymer.Base.detachedCallback; Polymer.Base._addFeature({ _hostStack: [], ready: function () { @@ -174,6 +175,13 @@ } else { this._attachedPending = true; } +}, +detachedCallback: function () { +if (this._readied) { +baseDetachedCallback.call(this); +} else { +this._attachedPending = false; +} } }); }());Polymer.ArraySplice = function () {
diff --git a/third_party/polymer/v1_0/components_summary.txt b/third_party/polymer/v1_0/components_summary.txt index a9375c5..d6c4f90 100644 --- a/third_party/polymer/v1_0/components_summary.txt +++ b/third_party/polymer/v1_0/components_summary.txt
@@ -306,7 +306,7 @@ Name: polymer Repository: https://github.com/Polymer/polymer.git -Tree: v1.9.1 -Revision: 9f3381a3d92c62d64cbf0296f7c967898a30d63d -Tree link: https://github.com/Polymer/polymer/tree/v1.9.1 +Tree: v1.11.2 +Revision: 1dcf3839b3ce058d2d87737674a25ecdd7343f9a +Tree link: https://github.com/Polymer/polymer/tree/v1.11.2
diff --git a/tools/checklicenses/checklicenses.py b/tools/checklicenses/checklicenses.py index b862b97..450f1de 100755 --- a/tools/checklicenses/checklicenses.py +++ b/tools/checklicenses/checklicenses.py
@@ -603,6 +603,10 @@ 'tools/gyp/test': [ 'UNKNOWN', ], + # Perf test data from Google Maps team. Not shipped. + 'tools/perf/page_sets/maps_perf_test': [ + 'UNKNOWN', + ], 'tools/python/google/__init__.py': [ 'UNKNOWN', ],
diff --git a/tools/mb/docs/user_guide.md b/tools/mb/docs/user_guide.md index ee653040..1bbef2f2 100644 --- a/tools/mb/docs/user_guide.md +++ b/tools/mb/docs/user_guide.md
@@ -132,6 +132,13 @@ Produces help output on the other subcommands +### `mb isolate` + +Builds a given (ninja) target and produces an `.isolated` file suitable +for then running the command either locally in an isolated environment, +or remotely by uploading it to an isolate server and running it under +swarming. See below for more information on isolates and swarming. + ### `mb lookup` Prints what command will be run by `mb gen` (like `mb gen -n` but does @@ -141,6 +148,24 @@ `--phase`, `-q/--quiet`, and `-v/--verbose` flags work as documented for `mb gen`. +### `mb run` + +Builds and runs a given (ninja) target. By default the target will +be run locally but isolated (i.e., outside of the source tree, just +as it would be run under swarming). If the `-s/--swarming` flag is +passed, the target will be built, run, uploaded to the isolate server, +and run under swarming. + +By default, a set of dimensions appropriate for running the target in the +default pool for the build will be provided. You can specify additional +dimensions with the `-d/--dimension` flags, and you can skip the default +dimensions with the `--no-default-dimensions` flag (which can be useful +if you need to run on devices or in a different pool). See below for more +information on isolates and swarming. + +In either case, any flags past `--` will be passed on to the command +to be run inside the isolate. + ### `mb validate` Does internal checking to make sure the config file is syntactically
diff --git a/tools/mb/mb.py b/tools/mb/mb.py index df21410..1bfe40d4 100755 --- a/tools/mb/mb.py +++ b/tools/mb/mb.py
@@ -3,7 +3,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -"""MB - the Meta-Build wrapper around GN +"""MB - the Meta-Build wrapper around GN. MB is a wrapper script for GN that can be used to generate build files for sets of canned configurations and analyze them. @@ -17,6 +17,7 @@ import json import os import pipes +import platform import pprint import re import shutil @@ -179,7 +180,6 @@ ' --test-launcher-retry-limit=0' '\n' ) - AddCommonOptions(subp) subp.add_argument('-j', '--jobs', dest='jobs', type=int, help='Number of jobs to pass to ninja') @@ -191,6 +191,14 @@ ' This can be either a regular path or a ' 'GN-style source-relative path like ' '//out/Default.')) + subp.add_argument('-s', '--swarmed', action='store_true', + help='Run under swarming with the default dimensions') + subp.add_argument('-d', '--dimension', default=[], action='append', nargs=2, + dest='dimensions', metavar='FOO bar', + help='dimension to filter on') + subp.add_argument('--no-default-dimensions', action='store_false', + dest='default_dimensions', default=True, + help='Do not automatically add dimensions to the task') subp.add_argument('target', nargs=1, help='ninja target to build and run') subp.add_argument('extra_args', nargs='*', @@ -313,20 +321,79 @@ if ret: return ret + if self.args.swarmed: + return self._RunUnderSwarming(build_dir, target) + else: + return self._RunLocallyIsolated(build_dir, target) + + def _RunUnderSwarming(self, build_dir, target): + # TODO(dpranke): Look up the information for the target in + # the //testing/buildbot.json file, if possible, so that we + # can determine the isolate target, command line, and additional + # swarming parameters, if possible. + # + # TODO(dpranke): Also, add support for sharding and merging results. + dimensions = [] + for k, v in self._DefaultDimensions() + self.args.dimensions: + dimensions += ['-d', k, v] + + cmd = [ + self.executable, + self.PathJoin('tools', 'swarming_client', 'isolate.py'), + 'archive', + '-s', + self.ToSrcRelPath('%s/%s.isolated' % (build_dir, target)), + '-I', 'isolateserver.appspot.com', + ] + ret, out, _ = self.Run(cmd, force_verbose=False) + if ret: + return ret + + isolated_hash = out.splitlines()[0].split()[0] + cmd = [ + self.executable, + self.PathJoin('tools', 'swarming_client', 'swarming.py'), + 'run', + '-s', isolated_hash, + '-I', 'isolateserver.appspot.com', + '-S', 'chromium-swarm.appspot.com', + ] + dimensions + if self.args.extra_args: + cmd += ['--'] + self.args.extra_args + ret, _, _ = self.Run(cmd, force_verbose=True, buffer_output=False) + return ret + + def _RunLocallyIsolated(self, build_dir, target): cmd = [ self.executable, self.PathJoin('tools', 'swarming_client', 'isolate.py'), 'run', '-s', self.ToSrcRelPath('%s/%s.isolated' % (build_dir, target)), - ] + ] if self.args.extra_args: - cmd += ['--'] + self.args.extra_args - - ret, _, _ = self.Run(cmd, force_verbose=False, buffer_output=False) - + cmd += ['--'] + self.args.extra_args + ret, _, _ = self.Run(cmd, force_verbose=True, buffer_output=False) return ret + def _DefaultDimensions(self): + if not self.args.default_dimensions: + return [] + + # This code is naive and just picks reasonable defaults per platform. + if self.platform == 'darwin': + os_dim = ('os', 'Mac-10.12') + elif self.platform.startswith('linux'): + os_dim = ('os', 'Ubuntu-14.04') + elif self.platform == 'win32': + os_dim = ('os', 'Windows-10-14393') + else: + raise MBErr('unrecognized platform string "%s"' % self.platform) + + return [('pool', 'Chrome'), + ('cpu', 'x86-64'), + os_dim] + def CmdBuildbucket(self): self.ReadConfigFile()
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index dc363bf..42d3c66 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -290,6 +290,8 @@ 'Android Release (Nexus 6P)': 'android_release_trybot_arm64', 'Android Release (Nexus 9)': 'android_release_trybot_arm64', 'Android Release (NVIDIA Shield TV)': 'android_release_trybot_arm64', + 'GPU Android arm Builder': 'gpu_tests_android_release_trybot', + 'GPU Android arm64 Builder': 'gpu_tests_android_release_trybot_arm64', 'GPU Linux Builder': 'gpu_fyi_tests_release_trybot', 'GPU Linux Ozone Builder': 'gpu_fyi_tests_ozone_linux_system_gbm_libdrm_release_trybot', 'GPU Linux Builder (dbg)': 'gpu_fyi_tests_debug_trybot', @@ -1357,6 +1359,10 @@ 'gpu_tests', 'internal_gles2_conform_tests', 'clang', 'debug_bot', 'minimal_symbols', ], + 'gpu_tests_android_release_trybot': [ + 'gpu_tests', 'android', 'release_trybot', + ], + 'gpu_tests_android_release_trybot_arm64': [ 'gpu_tests', 'android', 'release_trybot', 'arm64', ],
diff --git a/tools/mb/mb_unittest.py b/tools/mb/mb_unittest.py index 0cdc0162..dfd8f7f 100755 --- a/tools/mb/mb_unittest.py +++ b/tools/mb/mb_unittest.py
@@ -478,6 +478,33 @@ self.check(['run', '-c', 'debug_goma', '//out/Default', 'base_unittests'], files=files, ret=0) + def test_run_swarmed(self): + files = { + '/fake_src/testing/buildbot/gn_isolate_map.pyl': ( + "{'base_unittests': {" + " 'label': '//base:base_unittests'," + " 'type': 'raw'," + " 'args': []," + "}}\n" + ), + '/fake_src/out/Default/base_unittests.runtime_deps': ( + "base_unittests\n" + ), + } + + def run_stub(cmd, **_kwargs): + if 'isolate.py' in cmd[1]: + return 0, 'fake_hash base_unittests', '' + else: + return 0, '', '' + + mbw = self.fake_mbw(files=files) + mbw.Run = run_stub + self.check(['run', '-s', '-c', 'debug_goma', '//out/Default', + 'base_unittests'], mbw=mbw, ret=0) + self.check(['run', '-s', '-c', 'debug_goma', '-d', 'os', 'Win7', + '//out/Default', 'base_unittests'], mbw=mbw, ret=0) + def test_lookup(self): self.check(['lookup', '-c', 'debug_goma'], ret=0)
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index e271fbf2..a267d260 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -14270,6 +14270,8 @@ <int value="1204" label="METRICSPRIVATE_RECORDBOOLEAN"/> <int value="1205" label="METRICSPRIVATE_RECORDENUMERATIONVALUE"/> <int value="1206" label="DEVELOPERPRIVATE_NOTIFYDRAGINSTALLINPROGRESS"/> + <int value="1207" label="AUTOTESTPRIVATE_GETPRINTERLIST"/> + <int value="1208" label="DEVELOPERPRIVATE_GETEXTENSIONSIZE"/> </enum> <enum name="ExtensionIconState"> @@ -32323,6 +32325,17 @@ Request sent out and a connection error occurred (no valid HTTP response received). </int> + <int value="5" label="SUCCESS_FROM_CACHE"> + Success fetching the favicon from the cache without reaching out to the + server. + </int> + <int value="6" label="SUCCESS_FROM_SERVER"> + Success fetching the favicon from server. + </int> + <int value="7" label="FAILURE_WRITING_FAVICON_CACHE"> + Failed to write the favicon to cache, likely from attempting to add a + duplicate. + </int> </enum> <enum name="PassiveForcedListenerResultType"> @@ -33713,6 +33726,9 @@ </enum> <enum name="PhysicalWebInitialStateIosChrome"> + <obsolete> + Obsolete as of November 2017. + </obsolete> <int value="0" label="OPTOUT_BTOFF_LOCOFF_UNAUTH"/> <int value="1" label="OPTOUT_BTOFF_LOCOFF_AUTH"/> <int value="2" label="OPTOUT_BTOFF_LOCON_UNAUTH"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 1da7f7c3..af92e95 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -53925,6 +53925,14 @@ </summary> </histogram> +<histogram base="true" name="OfflinePages.AccessCount"> + <owner>jianli@chromium.org</owner> + <summary> + Number of accesses to the offline page since its creation. This is reported + when the offline page was deleted. + </summary> +</histogram> + <histogram name="OfflinePages.AccessEntryPoint" enum="OfflinePagesAccessEntryPoint"> <owner>jianli@chromium.org</owner> @@ -54733,14 +54741,14 @@ <summary>Length of time between two consecutive opens.</summary> </histogram> -<histogram name="OfflinePages.PageLifetime" units="minutes"> +<histogram base="true" name="OfflinePages.PageLifetime" units="minutes"> <owner>jianli@chromium.org</owner> <summary> Length of time between when an offline page was created and was removed. </summary> </histogram> -<histogram name="OfflinePages.PageSize" units="KB"> +<histogram base="true" name="OfflinePages.PageSize" units="KB"> <owner>jianli@chromium.org</owner> <summary>Size of the saved copy of an offline page.</summary> </histogram> @@ -55046,12 +55054,13 @@ </summary> </histogram> -<histogram name="OfflinePages.SavePageResult" enum="OfflinePagesSavePageResult"> +<histogram base="true" name="OfflinePages.SavePageResult" + enum="OfflinePagesSavePageResult"> <owner>jianli@chromium.org</owner> <summary>Result of saving an offline copy for a page.</summary> </histogram> -<histogram name="OfflinePages.SavePageTime" units="ms"> +<histogram base="true" name="OfflinePages.SavePageTime" units="ms"> <owner>jianli@chromium.org</owner> <summary> The amount of time taken to save an offline copy for a page. @@ -58879,6 +58888,14 @@ </summary> </histogram> +<histogram name="PartnerBookmark.LoadingTime" units="ms"> + <owner>wychen@chromium.org</owner> + <summary> + The time spent on loading partner bookmarks, from kickOffReading() to + bookmarkModelLoaded() callback. + </summary> +</histogram> + <histogram name="PartnerBookmark.Null" enum="BooleanNull"> <owner>wychen@chromium.org</owner> <summary> @@ -58897,6 +58914,15 @@ </summary> </histogram> +<histogram name="PartnerBookmark.TimeSinceLastEmptyRead" units="ms"> + <owner>wychen@chromium.org</owner> + <summary> + When trying to load the partner bookmarks, if no partner bookmark is read + last time, record the time elapsed since then. It is recorded no matter + whether loading would be skipped. + </summary> +</histogram> + <histogram name="PartnerBookmarksFaviconThrottle.NumEntries" units="entries"> <owner>thildebr@chromium.org</owner> <summary>
diff --git a/tools/perf/benchmarks/smoothness.py b/tools/perf/benchmarks/smoothness.py index 852d30c..bddba86 100644 --- a/tools/perf/benchmarks/smoothness.py +++ b/tools/perf/benchmarks/smoothness.py
@@ -177,7 +177,7 @@ class StoryExpectations(story_module.expectations.StoryExpectations): def SetExpectations(self): self.DisableStory( - 'http://map-test/performance.html', + 'maps_perf_test', [story_module.expectations.ANDROID_WEBVIEW], 'crbug.com/653993') return StoryExpectations()
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index 57c9d58..3078482 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -22,7 +22,6 @@ from telemetry import benchmark as benchmark_module from telemetry import decorators -from telemetry.story import expectations from py_utils import discover @@ -1048,17 +1047,11 @@ benchmark_list = current_benchmarks() for benchmark in benchmark_list: - exp = benchmark().GetExpectations() - disabled = 'all' in decorators.GetDisabledAttributes(benchmark) or any( - any(isinstance(condition, expectations.ALL.__class__) - for condition in conditions) - for (conditions, _) in exp.disabled_platforms) - emails = decorators.GetEmails(benchmark) if emails: emails = ', '.join(emails) metadata[benchmark.Name()] = BenchmarkMetadata( - emails, decorators.GetComponent(benchmark), disabled) + emails, decorators.GetComponent(benchmark), False) return metadata
diff --git a/tools/perf/page_sets/data/maps.json b/tools/perf/page_sets/data/maps.json deleted file mode 100644 index d7c05aaf..0000000 --- a/tools/perf/page_sets/data/maps.json +++ /dev/null
@@ -1,9 +0,0 @@ -{ - "archives": { - "http://map-test/performance.html": { - "DEFAULT": "maps_005.wprgo" - } - }, - "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.", - "platform_specific": true -}
diff --git a/tools/perf/page_sets/data/maps_005.wprgo.sha1 b/tools/perf/page_sets/data/maps_005.wprgo.sha1 deleted file mode 100644 index ba3efe2..0000000 --- a/tools/perf/page_sets/data/maps_005.wprgo.sha1 +++ /dev/null
@@ -1 +0,0 @@ -b328c5622f92ff82b0e7ad8b30dc46d74e0a4c05 \ No newline at end of file
diff --git a/tools/perf/page_sets/data/tough_path_rendering_cases.json b/tools/perf/page_sets/data/tough_path_rendering_cases.json index e3faf58..f52a84d 100644 --- a/tools/perf/page_sets/data/tough_path_rendering_cases.json +++ b/tools/perf/page_sets/data/tough_path_rendering_cases.json
@@ -1,12 +1,12 @@ { "archives": { - "GUIMark Vector Chart Test": { + "GUIMark_Vector_Chart_Test": { "DEFAULT": "tough_path_rendering_cases_002.wprgo" }, - "MotionMark Canvas Fill Shapes": { + "MotionMark_Canvas_Fill_Shapes": { "DEFAULT": "tough_path_rendering_cases_002.wprgo" }, - "MotionMark Canvas Stroke Shapes": { + "MotionMark_Canvas_Stroke_Shapes": { "DEFAULT": "tough_path_rendering_cases_002.wprgo" }, "http://ie.microsoft.com/testdrive/Performance/Chalkboard/": { @@ -21,4 +21,4 @@ }, "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.", "platform_specific": true -} \ No newline at end of file +}
diff --git a/tools/perf/page_sets/maps.py b/tools/perf/page_sets/maps.py index 8287904e1..1005857e 100644 --- a/tools/perf/page_sets/maps.py +++ b/tools/perf/page_sets/maps.py
@@ -2,65 +2,49 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import os + from telemetry.page import page as page_module from telemetry import story from page_sets import webgl_supported_shared_state +_MAPS_PERF_TEST_DIR = os.path.join(os.path.dirname(__file__), 'maps_perf_test') + class MapsPage(page_module.Page): """Google Maps benchmarks and pixel tests. - The Maps team gave us a build of their test. The only modification - to the test was to config.js, where the width and height query args - were set to 800 by 600. The WPR was recorded with: + The Maps team gave us a build of their test. The static files are stored in + //src/tools/perf/page_sets/maps_perf_test/. - tools/perf/record_wpr smoothness_maps --browser=system + Note: the file maps_perf_test/load_dataset is a large binary file (~3Mb), + hence we upload it to cloud storage & only check in the SHA1 hash. - This produced maps_???.wpr, maps_???.wpr.sha1 and maps.json. - - It's worth noting that telemetry no longer allows replaying a URL that - refers to localhost. If the recording was created for the locahost URL, one - can update the host name by running: - - web-page-replay/httparchive.py remap-host maps_004.wpr \ - localhost:8000 map-test - - (web-page-replay/ can be found in third_party/catapult/telemetry/third_party/) - - After updating the host name in the WPR archive, or recording a - newly-numbered WPR archive, please remember to update - content/test/gpu/gpu_tests/maps_integration_test.py (and potentially - its pixel expectations) as well. - - To upload the maps_???.wpr to cloud storage, one would run: - - depot_tools/upload_to_google_storage.py --bucket=chromium-telemetry \ - maps_???.wpr - """ + The command to upload it to cloud_storage is: + <path to depot_tools>/upload_to_google_storage.py \ + maps_perf_test/load_dataset --bucket=chromium-telemetry +""" def __init__(self, page_set): - url = 'http://map-test/performance.html' super(MapsPage, self).__init__( - url=url, + url='file://performance.html', + base_dir=_MAPS_PERF_TEST_DIR, page_set=page_set, shared_page_state_class=( webgl_supported_shared_state.WebGLSupportedSharedState), - name=url) + name='maps_perf_test') @property def skipped_gpus(self): # Skip this intensive test on low-end devices. crbug.com/464731 return ['arm'] - def RunNavigateSteps(self, action_runner): - super(MapsPage, self).RunNavigateSteps(action_runner) - action_runner.Wait(3) - def RunPageInteractions(self, action_runner): + action_runner.WaitForJavaScriptCondition('window.startTest !== undefined') + action_runner.EvaluateJavaScript('startTest()') with action_runner.CreateInteraction('MapAnimation'): - action_runner.WaitForJavaScriptCondition( - 'window.testMetrics != undefined', timeout=120) + action_runner.WaitForJavaScriptCondition('window.testDone', timeout=120) class MapsPageSet(story.StorySet): @@ -68,8 +52,6 @@ """ Google Maps examples """ def __init__(self): - super(MapsPageSet, self).__init__( - archive_data_file='data/maps.json', - cloud_storage_bucket=story.PUBLIC_BUCKET) + super(MapsPageSet,self).__init__(cloud_storage_bucket=story.PUBLIC_BUCKET) self.AddStory(MapsPage(self))
diff --git a/tools/perf/page_sets/maps_perf_test/config.js b/tools/perf/page_sets/maps_perf_test/config.js new file mode 100644 index 0000000..bfd3b4c7 --- /dev/null +++ b/tools/perf/page_sets/maps_perf_test/config.js
@@ -0,0 +1,4 @@ +// This file was generated by the _js_query_arg_file Skylark rule defined in +// maps/vectortown/performance/script/build_defs.bzl. + +var testConfig = "overridePixelRatio=1&title=chrome_smoothness_performancetest_config&nobudget=false&nodraw=false&noprefetch=true&viewport=basic&wait=true";
diff --git a/tools/perf/page_sets/maps_perf_test/load_dataset.sha1 b/tools/perf/page_sets/maps_perf_test/load_dataset.sha1 new file mode 100644 index 0000000..39495d8 --- /dev/null +++ b/tools/perf/page_sets/maps_perf_test/load_dataset.sha1
@@ -0,0 +1 @@ +e6bf26977c2fd80c18789d1f279d474096a7b0d1 \ No newline at end of file
diff --git a/tools/perf/page_sets/maps_perf_test/performance.html b/tools/perf/page_sets/maps_perf_test/performance.html new file mode 100644 index 0000000..bc4b498 --- /dev/null +++ b/tools/perf/page_sets/maps_perf_test/performance.html
@@ -0,0 +1,41 @@ +<!DOCTYPE html> +<html> + <head> + <title>Performance Test</title> + <script src="config.js"></script> + <script> + var saveTraceRegEx = /[?&]wtf=?([^&]*)/; + var saveTrace = + saveTraceRegEx.exec(testConfig) || saveTraceRegEx.exec(window.location.search); + + var needsTraceStart = false; + if (saveTrace && !window.wtf) { + needsTraceStart = true; + var wtfUrl = "https://tracing-framework.appspot.com/CURRENT/wtf_trace_web_js_compiled.js"; + if (saveTrace[1]) wtfUrl = saveTrace[1]; + document.write('<' + 'script type="text/javascript" src="' + wtfUrl + '"><' + '/script>'); + } + </script> + <style> + body #wtf-failed {display: none} + body.wtf-failed {background: red} + body.wtf-failed #wtf-failed {display: block; color: white} + </style> + </head> + <body> + <script src="tracked.js"></script> + <h1 id="wtf-failed">Failed to load tracing framework.</h1> + <script> + if (needsTraceStart && !window.wtf) { + document.body.className += "wtf-failed"; + } else { + var tracker = new Tracker(); + // Upload WTF traces to the metric tracker. + if (saveTrace) { + tracker.enableTracing(needsTraceStart, 'http-rel:/savetrace'); + } + tracker.run(); + } + </script> + </body> +</html>
diff --git a/tools/perf/page_sets/maps_perf_test/tracked.js b/tools/perf/page_sets/maps_perf_test/tracked.js new file mode 100644 index 0000000..e6c1cb6 --- /dev/null +++ b/tools/perf/page_sets/maps_perf_test/tracked.js
@@ -0,0 +1,1246 @@ +(function(){'use strict';for(var r,aa="function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){a!=Array.prototype&&a!=Object.prototype&&(a[b]=c.value)},ba="undefined"!=typeof window&&window===this?this:"undefined"!=typeof global&&null!=global?global:this,da=["Math","sign"],fa=0;fa<da.length-1;fa++){var ia=da[fa];ia in ba||(ba[ia]={});ba=ba[ia]}var ka=da[da.length-1],la=ba[ka],na=la?la:function(a){a=Number(a);return 0===a||isNaN(a)?a:0<a?1:-1}; +na!=la&&null!=na&&aa(ba,ka,{configurable:!0,writable:!0,value:na});var oa=oa||{},x=this;function B(a){return void 0!==a}function pa(a){return"string"==typeof a}function qa(a){return"number"==typeof a}function ra(a){a=a.split(".");for(var b=x,c=0;c<a.length;c++)if(b=b[a[c]],null==b)return null;return b}function sa(){}function ta(a){a.pb=void 0;a.sc=function(){return a.pb?a.pb:a.pb=new a}} +function ua(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array";if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("call"))return"function"}else return"null"; +else if("function"==b&&"undefined"==typeof a.call)return"object";return b}function va(a){return"array"==ua(a)}function xa(a){var b=ua(a);return"array"==b||"object"==b&&"number"==typeof a.length}function ya(a){return"function"==ua(a)}function za(a){var b=typeof a;return"object"==b&&null!=a||"function"==b}var Aa="closure_uid_"+(1E9*Math.random()>>>0),Ba=0;function Ca(a,b,c){return a.call.apply(a.bind,arguments)} +function Da(a,b,c){if(!a)throw Error();if(2<arguments.length){var d=Array.prototype.slice.call(arguments,2);return function(){var c=Array.prototype.slice.call(arguments);Array.prototype.unshift.apply(c,d);return a.apply(b,c)}}return function(){return a.apply(b,arguments)}}function D(a,b,c){Function.prototype.bind&&-1!=Function.prototype.bind.toString().indexOf("native code")?D=Ca:D=Da;return D.apply(null,arguments)} +function Ea(a,b){var c=Array.prototype.slice.call(arguments,1);return function(){var b=c.slice();b.push.apply(b,arguments);return a.apply(this,b)}}var E=Date.now||function(){return+new Date}; +function Fa(a){if(x.execScript)x.execScript(a,"JavaScript");else if(x.eval){if(null==Ha){try{x.eval("var _evalTest_ = 1;")}catch(d){}if("undefined"!=typeof x._evalTest_){try{delete x._evalTest_}catch(d){}Ha=!0}else Ha=!1}if(Ha)x.eval(a);else{var b=x.document,c=b.createElement("SCRIPT");c.type="text/javascript";c.defer=!1;c.appendChild(b.createTextNode(a));b.head.appendChild(c);b.head.removeChild(c)}}else throw Error("goog.globalEval not available");}var Ha=null; +function Ia(a,b){a=a.split(".");var c=x;a[0]in c||!c.execScript||c.execScript("var "+a[0]);for(var d;a.length&&(d=a.shift());)!a.length&&B(b)?c[d]=b:c[d]&&c[d]!==Object.prototype[d]?c=c[d]:c=c[d]={}}function F(a,b){function c(){}c.prototype=b.prototype;a.R=b.prototype;a.prototype=new c;a.prototype.constructor=a;a.Xf=function(a,c,f){for(var d=Array(arguments.length-2),e=2;e<arguments.length;e++)d[e-2]=arguments[e];return b.prototype[c].apply(a,d)}};function Ja(a){if(Error.captureStackTrace)Error.captureStackTrace(this,Ja);else{var b=Error().stack;b&&(this.stack=b)}a&&(this.message=String(a))}F(Ja,Error);Ja.prototype.name="CustomError";var Ka=Array.prototype.indexOf?function(a,b){return Array.prototype.indexOf.call(a,b,void 0)}:function(a,b){if(pa(a))return pa(b)&&1==b.length?a.indexOf(b,0):-1;for(var c=0;c<a.length;c++)if(c in a&&a[c]===b)return c;return-1},La=Array.prototype.lastIndexOf?function(a,b){return Array.prototype.lastIndexOf.call(a,b,a.length-1)}:function(a,b){var c=a.length-1;0>c&&(c=Math.max(0,a.length+c));if(pa(a))return pa(b)&&1==b.length?a.lastIndexOf(b,c):-1;for(;0<=c;c--)if(c in a&&a[c]===b)return c;return-1}, +Ma=Array.prototype.forEach?function(a,b,c){Array.prototype.forEach.call(a,b,c)}:function(a,b,c){for(var d=a.length,e=pa(a)?a.split(""):a,f=0;f<d;f++)f in e&&b.call(c,e[f],f,a)},Na=Array.prototype.filter?function(a,b){return Array.prototype.filter.call(a,b,void 0)}:function(a,b){for(var c=a.length,d=[],e=0,f=pa(a)?a.split(""):a,g=0;g<c;g++)if(g in f){var h=f[g];b.call(void 0,h,g,a)&&(d[e++]=h)}return d},Oa=Array.prototype.reduce?function(a,b,c){return Array.prototype.reduce.call(a,b,c)}:function(a, +b,c){var d=c;Ma(a,function(c,f){d=b.call(void 0,d,c,f,a)});return d},Pa=Array.prototype.some?function(a,b){return Array.prototype.some.call(a,b,void 0)}:function(a,b){for(var c=a.length,d=pa(a)?a.split(""):a,e=0;e<c;e++)if(e in d&&b.call(void 0,d[e],e,a))return!0;return!1},Qa=Array.prototype.every?function(a,b){return Array.prototype.every.call(a,b,void 0)}:function(a,b){for(var c=a.length,d=pa(a)?a.split(""):a,e=0;e<c;e++)if(e in d&&!b.call(void 0,d[e],e,a))return!1;return!0}; +function Ra(a){a:{var b=Sa;for(var c=a.length,d=pa(a)?a.split(""):a,e=0;e<c;e++)if(e in d&&b.call(void 0,d[e],e,a)){b=e;break a}b=-1}return 0>b?null:pa(a)?a.charAt(b):a[b]}function Ta(a,b){b=Ka(a,b);var c;(c=0<=b)&&Array.prototype.splice.call(a,b,1);return c}function Ua(a){return Array.prototype.concat.apply([],arguments)}function Va(a){var b=a.length;if(0<b){for(var c=Array(b),d=0;d<b;d++)c[d]=a[d];return c}return[]} +function Wa(a,b,c){return 2>=arguments.length?Array.prototype.slice.call(a,b):Array.prototype.slice.call(a,b,c)}function Xa(a,b){if(!xa(a)||!xa(b)||a.length!=b.length)return!1;for(var c=a.length,d=Ya,e=0;e<c;e++)if(!d(a[e],b[e]))return!1;return!0}function Za(a,b){return a>b?1:a<b?-1:0}function Ya(a,b){return a===b};var $a=String.prototype.trim?function(a){return a.trim()}:function(a){return/^[\s\xa0]*([\s\S]*?)[\s\xa0]*$/.exec(a)[1]}; +function ab(a,b){var c=0;a=$a(String(a)).split(".");b=$a(String(b)).split(".");for(var d=Math.max(a.length,b.length),e=0;0==c&&e<d;e++){var f=a[e]||"",g=b[e]||"";do{f=/(\d*)(\D*)(.*)/.exec(f)||["","","",""];g=/(\d*)(\D*)(.*)/.exec(g)||["","","",""];if(0==f[0].length&&0==g[0].length)break;c=bb(0==f[1].length?0:parseInt(f[1],10),0==g[1].length?0:parseInt(g[1],10))||bb(0==f[2].length,0==g[2].length)||bb(f[2],g[2]);f=f[3];g=g[3]}while(0==c)}return c}function bb(a,b){return a<b?-1:a>b?1:0};var cb;a:{var db=x.navigator;if(db){var eb=db.userAgent;if(eb){cb=eb;break a}}cb=""}function fb(a){return-1!=cb.indexOf(a)};function gb(a,b,c){for(var d in a)b.call(c,a[d],d,a)}var hb="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" ");function ib(a,b){for(var c,d,e=1;e<arguments.length;e++){d=arguments[e];for(c in d)a[c]=d[c];for(var f=0;f<hb.length;f++)c=hb[f],Object.prototype.hasOwnProperty.call(d,c)&&(a[c]=d[c])}};function jb(){return(fb("Chrome")||fb("CriOS"))&&!fb("Edge")};function kb(){return fb("iPhone")&&!fb("iPod")&&!fb("iPad")};function lb(a){lb[" "](a);return a}lb[" "]=sa;function mb(a,b){var c=nb;return Object.prototype.hasOwnProperty.call(c,a)?c[a]:c[a]=b(a)};var ob=fb("Opera"),pb=fb("Trident")||fb("MSIE"),qb=fb("Edge"),rb=fb("Gecko")&&!(-1!=cb.toLowerCase().indexOf("webkit")&&!fb("Edge"))&&!(fb("Trident")||fb("MSIE"))&&!fb("Edge"),sb=-1!=cb.toLowerCase().indexOf("webkit")&&!fb("Edge"),tb=fb("Windows");function ub(){var a=x.document;return a?a.documentMode:void 0}var vb; +a:{var wb="",xb=function(){var a=cb;if(rb)return/rv:([^\);]+)(\)|;)/.exec(a);if(qb)return/Edge\/([\d\.]+)/.exec(a);if(pb)return/\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(a);if(sb)return/WebKit\/(\S+)/.exec(a);if(ob)return/(?:Version)[ \/]?(\S+)/.exec(a)}();xb&&(wb=xb?xb[1]:"");if(pb){var yb=ub();if(null!=yb&&yb>parseFloat(wb)){vb=String(yb);break a}}vb=wb}var zb=vb,nb={};function Ab(a){return mb(a,function(){return 0<=ab(zb,a)})}var Bb;var Cb=x.document; +Bb=Cb&&pb?ub()||("CSS1Compat"==Cb.compatMode?parseInt(zb,10):5):void 0;function Db(a){var b=x.onerror,c=!1;sb&&!Ab("535.3")&&(c=!c);x.onerror=function(d,e,f,g,h){b&&b(d,e,f,g,h);a({message:d,fileName:e,line:f,lineNumber:f,Zf:g,error:h});return c}};var Eb=[],Fb=[],Gb=!1;function Hb(a){Eb[Eb.length]=a;if(Gb)for(var b=0;b<Fb.length;b++)a(D(Fb[b].a,Fb[b]))};function Ib(){this.u=this.u;this.o=this.o}Ib.prototype.u=!1;Ib.prototype.O=function(){return this.u};Ib.prototype.$=function(){this.u||(this.u=!0,this.X())};function Jb(a,b){Kb(a,Ea(Lb,b))}function Kb(a,b){a.u?B(void 0)?b.call(void 0):b():(a.o||(a.o=[]),a.o.push(B(void 0)?D(b,void 0):b))}Ib.prototype.X=function(){if(this.o)for(;this.o.length;)this.o.shift()()};function Lb(a){a&&"function"==typeof a.$&&a.$()};var Mb;(Mb=!pb)||(Mb=9<=Number(Bb));var Nb=Mb,Ob=pb&&!Ab("9"),Pb=function(){if(!x.addEventListener||!Object.defineProperty)return!1;var a=!1,b=Object.defineProperty({},"passive",{get:function(){a=!0}});x.addEventListener("test",sa,b);x.removeEventListener("test",sa,b);return a}();function Qb(a,b){this.type=a;this.a=this.target=b;this.Re=!0}Qb.prototype.b=function(){this.Re=!1};function Rb(a,b){Qb.call(this,a?a.type:"");this.relatedTarget=this.a=this.target=null;this.button=this.screenY=this.screenX=this.clientY=this.clientX=0;this.key="";this.metaKey=this.shiftKey=this.altKey=this.ctrlKey=!1;this.pointerId=0;this.pointerType="";this.c=null;if(a){var c=this.type=a.type,d=a.changedTouches?a.changedTouches[0]:null;this.target=a.target||a.srcElement;this.a=b;if(b=a.relatedTarget){if(rb){a:{try{lb(b.nodeName);var e=!0;break a}catch(f){}e=!1}e||(b=null)}}else"mouseover"==c?b= +a.fromElement:"mouseout"==c&&(b=a.toElement);this.relatedTarget=b;null===d?(this.clientX=void 0!==a.clientX?a.clientX:a.pageX,this.clientY=void 0!==a.clientY?a.clientY:a.pageY,this.screenX=a.screenX||0,this.screenY=a.screenY||0):(this.clientX=void 0!==d.clientX?d.clientX:d.pageX,this.clientY=void 0!==d.clientY?d.clientY:d.pageY,this.screenX=d.screenX||0,this.screenY=d.screenY||0);this.button=a.button;this.key=a.key||"";this.ctrlKey=a.ctrlKey;this.altKey=a.altKey;this.shiftKey=a.shiftKey;this.metaKey= +a.metaKey;this.pointerId=a.pointerId||0;this.pointerType=pa(a.pointerType)?a.pointerType:Sb[a.pointerType]||"";this.c=a;a.defaultPrevented&&this.b()}}F(Rb,Qb);var Sb={2:"touch",3:"pen",4:"mouse"};Rb.prototype.b=function(){Rb.R.b.call(this);var a=this.c;if(a.preventDefault)a.preventDefault();else if(a.returnValue=!1,Ob)try{if(a.ctrlKey||112<=a.keyCode&&123>=a.keyCode)a.keyCode=-1}catch(b){}};var Tb="closure_listenable_"+(1E6*Math.random()|0);function Ub(a){return!(!a||!a[Tb])}var Vb=0;function Wb(a,b,c,d,e){this.listener=a;this.a=null;this.src=b;this.type=c;this.capture=!!d;this.ad=e;this.key=++Vb;this.fc=this.Vc=!1}function Xb(a){a.fc=!0;a.listener=null;a.a=null;a.src=null;a.ad=null};function Yb(a){this.src=a;this.a={};this.b=0}Yb.prototype.add=function(a,b,c,d,e){var f=a.toString();a=this.a[f];a||(a=this.a[f]=[],this.b++);var g=Zb(a,b,d,e);-1<g?(b=a[g],c||(b.Vc=!1)):(b=new Wb(b,this.src,f,!!d,e),b.Vc=c,a.push(b));return b};function $b(a,b){var c=b.type;if(!(c in a.a))return!1;var d=Ta(a.a[c],b);d&&(Xb(b),0==a.a[c].length&&(delete a.a[c],a.b--));return d}Yb.prototype.tc=function(a,b,c,d){a=this.a[a.toString()];var e=-1;a&&(e=Zb(a,b,c,d));return-1<e?a[e]:null}; +function Zb(a,b,c,d){for(var e=0;e<a.length;++e){var f=a[e];if(!f.fc&&f.listener==b&&f.capture==!!c&&f.ad==d)return e}return-1};var ac="closure_lm_"+(1E6*Math.random()|0),bc={},cc=0;function dc(a,b,c,d,e){if(d&&d.once)return ec(a,b,c,d,e);if(va(b)){for(var f=0;f<b.length;f++)dc(a,b[f],c,d,e);return null}c=fc(c);return Ub(a)?a.cb(b,c,za(d)?!!d.capture:!!d,e):gc(a,b,c,!1,d,e)} +function gc(a,b,c,d,e,f){if(!b)throw Error("Invalid event type");var g=za(e)?!!e.capture:!!e,h=hc(a);h||(a[ac]=h=new Yb(a));c=h.add(b,c,d,g,f);if(c.a)return c;d=ic();c.a=d;d.src=a;d.listener=c;if(a.addEventListener)Pb||(e=g),void 0===e&&(e=!1),a.addEventListener(b.toString(),d,e);else if(a.attachEvent)a.attachEvent(jc(b.toString()),d);else if(a.addListener&&a.removeListener)a.addListener(d);else throw Error("addEventListener and attachEvent are unavailable.");cc++;return c} +function ic(){var a=kc,b=Nb?function(c){return a.call(b.src,b.listener,c)}:function(c){c=a.call(b.src,b.listener,c);if(!c)return c};return b}function ec(a,b,c,d,e){if(va(b)){for(var f=0;f<b.length;f++)ec(a,b[f],c,d,e);return null}c=fc(c);return Ub(a)?a.cc(b,c,za(d)?!!d.capture:!!d,e):gc(a,b,c,!0,d,e)}function lc(a,b,c,d,e){if(va(b))for(var f=0;f<b.length;f++)lc(a,b[f],c,d,e);else d=za(d)?!!d.capture:!!d,c=fc(c),Ub(a)?a.Sd(b,c,d,e):a&&(a=hc(a))&&(b=a.tc(b,c,d,e))&&mc(b)} +function mc(a){if(qa(a)||!a||a.fc)return!1;var b=a.src;if(Ub(b))return $b(b.Cb,a);var c=a.type,d=a.a;b.removeEventListener?b.removeEventListener(c,d,a.capture):b.detachEvent?b.detachEvent(jc(c),d):b.addListener&&b.removeListener&&b.removeListener(d);cc--;(c=hc(b))?($b(c,a),0==c.b&&(c.src=null,b[ac]=null)):Xb(a);return!0}function nc(a){if(a)if(Ub(a))a.Ld(void 0);else if(a=hc(a)){var b=0,c;for(c in a.a)for(var d=a.a[c].concat(),e=0;e<d.length;++e)mc(d[e])&&++b}} +function jc(a){return a in bc?bc[a]:bc[a]="on"+a}function oc(a,b,c,d){var e=!0;if(a=hc(a))if(b=a.a[b.toString()])for(b=b.concat(),a=0;a<b.length;a++){var f=b[a];f&&f.capture==c&&!f.fc&&(f=pc(f,d),e=e&&!1!==f)}return e}function pc(a,b){var c=a.listener,d=a.ad||a.src;a.Vc&&mc(a);return c.call(d,b)} +function kc(a,b){if(a.fc)return!0;if(!Nb){var c=b||ra("window.event");b=new Rb(c,this);var d=!0;if(!(0>c.keyCode||void 0!=c.returnValue)){a:{var e=!1;if(0==c.keyCode)try{c.keyCode=-1;break a}catch(g){e=!0}if(e||void 0==c.returnValue)c.returnValue=!0}c=[];for(e=b.a;e;e=e.parentNode)c.push(e);a=a.type;for(e=c.length-1;0<=e;e--){b.a=c[e];var f=oc(c[e],a,!0,b);d=d&&f}for(e=0;e<c.length;e++)b.a=c[e],f=oc(c[e],a,!1,b),d=d&&f}return d}return pc(a,new Rb(b,this))} +function hc(a){a=a[ac];return a instanceof Yb?a:null}var qc="__closure_events_fn_"+(1E9*Math.random()>>>0);function fc(a){if(ya(a))return a;a[qc]||(a[qc]=function(b){return a.handleEvent(b)});return a[qc]}Hb(function(a){kc=a(kc)});function rc(){Ib.call(this);this.Cb=new Yb(this);this.kf=this;this.Ed=null}F(rc,Ib);rc.prototype[Tb]=!0;r=rc.prototype;r.addEventListener=function(a,b,c,d){dc(this,a,b,c,d)};r.removeEventListener=function(a,b,c,d){lc(this,a,b,c,d)}; +r.dispatchEvent=function(a){var b,c=this.Ed;if(c)for(b=[];c;c=c.Ed)b.push(c);c=this.kf;var d=a.type||a;if(pa(a))a=new Qb(a,c);else if(a instanceof Qb)a.target=a.target||c;else{var e=a;a=new Qb(d,c);ib(a,e)}e=!0;if(b)for(var f=b.length-1;0<=f;f--){var g=a.a=b[f];e=sc(g,d,!0,a)&&e}g=a.a=c;e=sc(g,d,!0,a)&&e;e=sc(g,d,!1,a)&&e;if(b)for(f=0;f<b.length;f++)g=a.a=b[f],e=sc(g,d,!1,a)&&e;return e};r.X=function(){rc.R.X.call(this);this.Ld();this.Ed=null}; +r.cb=function(a,b,c,d){return this.Cb.add(String(a),b,!1,c,d)};r.cc=function(a,b,c,d){return this.Cb.add(String(a),b,!0,c,d)};r.Sd=function(a,b,c,d){var e=this.Cb;a=String(a).toString();if(a in e.a){var f=e.a[a];b=Zb(f,b,c,d);-1<b&&(Xb(f[b]),Array.prototype.splice.call(f,b,1),0==f.length&&(delete e.a[a],e.b--))}};r.Ld=function(a){if(this.Cb){var b=this.Cb;a=a&&a.toString();var c=0,d;for(d in b.a)if(!a||d==a){for(var e=b.a[d],f=0;f<e.length;f++)++c,Xb(e[f]);delete b.a[d];b.b--}}}; +function sc(a,b,c,d){b=a.Cb.a[String(b)];if(!b)return!0;b=b.concat();for(var e=!0,f=0;f<b.length;++f){var g=b[f];if(g&&!g.fc&&g.capture==c){var h=g.listener,k=g.ad||g.src;g.Vc&&$b(a.Cb,g);e=!1!==h.call(k,d)&&e}}return e&&0!=d.Re}r.tc=function(a,b,c,d){return this.Cb.tc(String(a),b,c,d)};function tc(a){switch(a){case 5:case 3:case 13:case 4:case 17:case 18:case 8:case 14:case 31:return 0;case 1:case 6:case 16:case 30:return 1;case 9:case 11:case 12:return 2;case 2:case 7:case 15:return 5;default:return-1}};var uc=fb("Firefox"),vc=kb()||fb("iPod"),wc=fb("iPad"),xc=fb("Android")&&!(jb()||fb("Firefox")||fb("Opera")||fb("Silk")),yc=jb(),zc=fb("Safari")&&!(jb()||fb("Coast")||fb("Opera")||fb("Edge")||fb("Silk")||fb("Android"))&&!(kb()||fb("iPad")||fb("iPod"));var Ac=null,Bc=null,Cc=null;function Dc(a,b){Ec();b=b?Cc:Ac;for(var c=[],d=0;d<a.length;d+=3){var e=a[d],f=d+1<a.length,g=f?a[d+1]:0,h=d+2<a.length,k=h?a[d+2]:0,l=e>>2;e=(e&3)<<4|g>>4;g=(g&15)<<2|k>>6;k&=63;h||(k=64,f||(g=64));c.push(b[l],b[e],b[g],b[k])}return c.join("")}function Fc(a){var b=[];Gc(a,function(a){b.push(a)});return b} +function Hc(a){var b=a.length,c=0;"="===a[b-2]?c=2:"="===a[b-1]&&(c=1);var d=new Uint8Array(Math.ceil(3*b/4)-c),e=0;Gc(a,function(a){d[e++]=a});return d.subarray(0,e)}function Gc(a,b){function c(b){for(;d<a.length;){var c=a.charAt(d++),e=Bc[c];if(null!=e)return e;if(!/^[\s\xa0]*$/.test(c))throw Error("Unknown base64 encoding at char: "+c);}return b}Ec();for(var d=0;;){var e=c(-1),f=c(0),g=c(64),h=c(64);if(64===h&&-1===e)break;b(e<<2|f>>4);64!=g&&(b(f<<4&240|g>>2),64!=h&&b(g<<6&192|h))}} +function Ec(){if(!Ac){Ac={};Bc={};Cc={};for(var a=0;65>a;a++)Ac[a]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(a),Bc[Ac[a]]=a,Cc[a]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.".charAt(a),62<=a&&(Bc["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.".charAt(a)]=a)}};var Ic=0,Jc=0;function Kc(a,b){var c=b&2147483648;c&&(a=~a+1>>>0,b=~b>>>0,0==a&&(b=b+1>>>0));a=4294967296*b+a;return c?-a:a}function Lc(a,b){return String.fromCharCode(a>>>0&255,a>>>8&255,a>>>16&255,a>>>24&255,b>>>0&255,b>>>8&255,b>>>16&255,b>>>24&255)}var Mc="0123456789abcdef".split(""); +function Nc(a,b){function c(a){for(var b=1E7,c=0;7>c;c++){b/=10;var d=a/b%10>>>0;if(0!=d||f)f=!0,g+=e[d]}}if(2097151>=b)return""+(4294967296*b+a);var d=(a>>>24|b<<8)>>>0&16777215;b=b>>16&65535;a=(a&16777215)+6777216*d+6710656*b;d+=8147497*b;b*=2;1E7<=a&&(d+=Math.floor(a/1E7),a%=1E7);1E7<=d&&(b+=Math.floor(d/1E7),d%=1E7);var e=Mc,f=!1,g="";(b||f)&&c(b);(d||f)&&c(d);(a||f)&&c(a);return g} +function Oc(a,b){var c=a.charCodeAt(4),d=a.charCodeAt(5),e=a.charCodeAt(6),f=a.charCodeAt(7);Ic=a.charCodeAt(0)+(a.charCodeAt(1)<<8)+(a.charCodeAt(2)<<16)+(a.charCodeAt(3)<<24)>>>0;Jc=c+(d<<8)+(e<<16)+(f<<24)>>>0;c=Ic;a=Jc;if(b){b=c;c=a;if(a=c&2147483648)b=~b+1>>>0,c=~c+(0==b?1:0)>>>0;b=Nc(b,c);b=a?"-"+b:b}else b=Nc(c,a);return b}function Pc(a,b){for(var c=Array(a.length),d=0;d<a.length;d++)c[d]=Oc(a[d],b);return c};function Qc(a,b,c){this.c=this.h=this.a=null;this.g=0;this.b=null;this.f=!0;Rc(this,a,b,c)}function Rc(a,b,c,d){b&&c&&(a.a=b,a.h=c);a.c=d||null;a.g=0;a.b=null;a.f=!a.a&&!a.c;a.next()}var Sc=[];function Tc(a,b,c){if(Sc.length){var d=Sc.pop();Rc(d,a,b,c);return d}return new Qc(a,b,c)}function Uc(a){a.clear();100>Sc.length&&Sc.push(a)}Qc.prototype.clear=function(){this.a&&Vc(this.a);this.c=this.h=this.a=null;this.g=0;this.b=null;this.f=!0};Qc.prototype.get=function(){return this.b};Qc.prototype.kb=function(){return this.f}; +Qc.prototype.next=function(){var a=this.b;this.a?this.a.kb()?(this.b=null,this.f=!0):this.b=this.h.call(this.a):this.c&&(this.g==this.c.length?(this.b=null,this.f=!0):this.b=this.c[this.g++]);return a};function Wc(a,b,c){this.b=null;this.f=this.g=this.a=this.c=this.h=0;this.i=!1;a&&Xc(this,a,b,c)}var Yc=[];function Zc(a,b,c){if(Yc.length){var d=Yc.pop();a&&Xc(d,a,b,c);return d}return new Wc(a,b,c)}function Vc(a){a.clear();100>Yc.length&&Yc.push(a)}r=Wc.prototype; +r.clear=function(){this.b=null;this.a=this.c=this.h=0;this.i=!1};function Xc(a,b,c,d){b=b.constructor===Uint8Array?b:b.constructor===ArrayBuffer?new Uint8Array(b):b.constructor===Array?new Uint8Array(b):b.constructor===String?Hc(b):new Uint8Array(0);a.b=b;a.h=B(c)?c:0;a.c=B(d)?a.h+d:a.b.length;a.a=a.h}r.reset=function(){this.a=this.h};r.kb=function(){return this.a==this.c};r.getError=function(){return this.i||0>this.a||this.a>this.c}; +function $c(a){for(var b,c=0,d,e=0;4>e;e++)if(b=a.b[a.a++],c|=(b&127)<<7*e,128>b){a.g=c>>>0;a.f=0;return}b=a.b[a.a++];c|=(b&127)<<28;d=0|(b&127)>>4;if(128>b)a.g=c>>>0,a.f=d>>>0;else{for(e=0;5>e;e++)if(b=a.b[a.a++],d|=(b&127)<<7*e+3,128>b){a.g=c>>>0;a.f=d>>>0;return}a.i=!0}}function ad(a){for(;a.b[a.a]&128;)a.a++;a.a++} +r.ca=function(){var a=this.b;var b=a[this.a+0];var c=b&127;if(128>b)return this.a+=1,c;b=a[this.a+1];c|=(b&127)<<7;if(128>b)return this.a+=2,c;b=a[this.a+2];c|=(b&127)<<14;if(128>b)return this.a+=3,c;b=a[this.a+3];c|=(b&127)<<21;if(128>b)return this.a+=4,c;b=a[this.a+4];c|=(b&15)<<28;if(128>b)return this.a+=5,c>>>0;this.a+=5;128<=a[this.a++]&&128<=a[this.a++]&&128<=a[this.a++]&&128<=a[this.a++]&&this.a++;return c};r.Ma=Wc.prototype.ca;r.da=function(){var a=this.ca();return a>>>1^-(a&1)}; +function bd(a){$c(a);return Kc(a.g,a.f)}r.Eb=function(){var a=this.b[this.a+0],b=this.b[this.a+1],c=this.b[this.a+2],d=this.b[this.a+3];this.a+=4;return(a<<0|b<<8|c<<16|d<<24)>>>0};r.zd=function(){var a=this.Eb(),b=2*(a>>31)+1,c=a>>>23&255;a&=8388607;return 255==c?a?NaN:Infinity*b:0==c?b*Math.pow(2,-149)*a:b*Math.pow(2,c-150)*(a+Math.pow(2,23))}; +function cd(a){var b=a.Eb(),c=a.Eb();a=2*(c>>31)+1;var d=c>>>20&2047;b=4294967296*(c&1048575)+b;return 2047==d?b?NaN:Infinity*a:0==d?a*Math.pow(2,-1074)*b:a*Math.pow(2,d-1075)*(b+4503599627370496)} +function dd(a,b){var c=a.b,d=a.a,e=d+b;b=[];for(var f="";d<e;){var g=c[d++];if(128>g)b.push(g);else if(192>g)continue;else if(224>g){var h=c[d++];b.push((g&31)<<6|h&63)}else if(240>g){h=c[d++];var k=c[d++];b.push((g&15)<<12|(h&63)<<6|k&63)}else if(248>g){h=c[d++];k=c[d++];var l=c[d++];g=(g&7)<<18|(h&63)<<12|(k&63)<<6|l&63;g-=65536;b.push((g>>10&1023)+55296,(g&1023)+56320)}8192<=b.length&&(f+=String.fromCharCode.apply(null,b),b.length=0)}c=f;if(8192>=b.length)b=String.fromCharCode.apply(null,b);else{e= +"";for(f=0;f<b.length;f+=8192)g=Wa(b,f,f+8192),e+=String.fromCharCode.apply(null,g);b=e}a.a=d;return c+b}r.Lf=function(){var a=this.ca();return dd(this,a)};r.De=function(){$c(this);return Lc(this.g,this.f)};r.Ce=function(){var a=this.b,b=this.a,c=a[b+0],d=a[b+1],e=a[b+2],f=a[b+3],g=a[b+4],h=a[b+5],k=a[b+6];a=a[b+7];this.a+=8;return String.fromCharCode(c,d,e,f,g,h,k,a)};function ed(a,b,c){this.c=Zc(a,b,c);this.b=this.c.a;this.f=this.a=-1;this.g=!1}var fd=[];function gd(a,b,c){if(fd.length){var d=fd.pop();a&&Xc(d.c,a,b,c);return d}return new ed(a,b,c)}function hd(a){a.c.clear();a.a=-1;a.f=-1;a.g=!1;100>fd.length&&fd.push(a)}function id(a){return a.c.a}function jd(a){return a.c.b}ed.prototype.getError=function(){return this.g||this.c.getError()};ed.prototype.reset=function(){this.c.reset();this.f=this.a=-1}; +function G(a){if(a.c.kb()||a.getError())return!1;a.b=a.c.a;var b=a.c.ca(),c=b&7;if(0!=c&&5!=c&&1!=c&&2!=c&&3!=c&&4!=c)return a.g=!0,!1;a.a=b>>>3;a.f=c;return!0}function kd(a){if(2!=a.f)H(a);else{var b=a.c.ca();a=a.c;a.a+=b}} +function H(a){switch(a.f){case 0:0!=a.f?H(a):ad(a.c);break;case 1:1!=a.f?H(a):(a=a.c,a.a+=8);break;case 2:kd(a);break;case 5:5!=a.f?H(a):(a=a.c,a.a+=4);break;case 3:var b=[a.a];do{if(!G(a)){a.g=!0;break}if(3==a.f)b.push(a.a);else if(4==a.f&&a.a!=b.pop()){a.g=!0;break}}while(0<b.length)}} +function ld(a,b){a.f=tc(b);switch(b){case 1:return cd(a.c);case 2:return md(a);case 3:return bd(a.c);case 4:return a=a.c,$c(a),4294967296*a.f+a.g;case 5:return J(a);case 6:return a=a.c,b=a.Eb(),4294967296*a.Eb()+b;case 7:return nd(a);case 8:return K(a);case 9:return L(a);case 10:case 11:case 12:return od(a);case 13:return M(a);case 14:return N(a);case 15:a=a.c;b=a.b[a.a+0];var c=a.b[a.a+1],d=a.b[a.a+2],e=a.b[a.a+3];a.a+=4;return b<<0|c<<8|d<<16|e<<24;case 16:return b=a.c,a=b.Eb(),b=b.Eb(),Kc(a,b); +case 17:return a.c.da();case 18:return b=a.c,$c(b),a=b.g,c=b.f,b=a&1,a=(a>>>1|c<<31)>>>0,c>>>=1,b&&(a=a+1>>>0,0==a&&(c=c+1>>>0)),a=4294967296*c+a,b?-a:a;case 30:return pd(a);case 31:return qd(a)}return 0}function O(a,b,c){var d=a.c.c,e=a.c.ca();e=a.c.a+e;a.c.c=e;c(b,a);a.c.a=e;a.c.c=d}function J(a){return a.c.Ma()}function M(a){return a.c.ca()}function nd(a){return a.c.Eb()}function md(a){return a.c.zd()}function K(a){return!!a.c.ca()}function N(a){return bd(a.c)} +function L(a){var b=a.c.ca();return dd(a.c,b)}function od(a){var b=a.c.ca();a=a.c;if(0>b||a.a+b>a.b.length)a.i=!0,b=new Uint8Array(0);else{var c=a.b.subarray(a.a,a.a+b);a.a+=b;b=c}return b}function qd(a){return a.c.De()}function pd(a){return a.c.Ce()};function rd(a,b,c,d,e,f,g){this.c=a;this.b=b;this.a=B(c)?c:null;this.i=B(d)?d:null;this.h=B(e)?e:null;this.f=B(f)?f:null;this.g=B(g)?g:null}function sd(){this.c=-1;this.value=this.a=this.b=this.start=this.buffer=null}var td=[],ud=0;function vd(a,b,c,d,e,f){if(ud){ud--;var g=td[ud];td[ud]=null}else g=new sd;var h=g;h.c=a;h.buffer=B(c)?c:null;h.start=B(d)?d:null;h.b=B(e)?e:null;h.a=B(f)?f:null;h.value=B(b)?b:null;return g} +function wd(a){if(a){null!=a.buffer&&null!=a.start&&null!=a.b&&null!=a.a&&null!=a.value&&(a.a.i&&a.a.i(a.value),a.value=null);a.c=-1;a.buffer=null;a.start=null;a.b=null;a.a=null;a.value=null;var b=ud;1E3>b&&(td[b]=a,ud++)}} +function xd(a){if(null==a)return null;for(var b=[],c=0;c<a.length;c++){var d=a[c],e=new sd;e.c=d.c;null!=d.value&&null!=d.a?(e.a=d.a,d.a.f?e.value=d.a.f(d.value):12==d.a.b?e.value=new Uint8Array(d.value):e.value=d.value):null!=d.buffer&&null!=d.start&&null!=d.b&&(e.buffer=new Uint8Array(d.buffer.buffer.slice(d.start,d.b)),e.start=0,e.b=d.b-d.start);b.push(e)}return b}function yd(a,b,c,d,e,f,g,h){c=new rd(b,c,d,e,f,g,h);for(d=0;d<a.length;d++)if(a[d].c==b){a[d]=c;return}a.push(c)};function zd(a,b,c){var d=Wc.prototype.Ma;return a&&null!=b&&null!=c&&d?(a=Zc(a,b,c-b),a.ca(),a.ca(),Tc(a,d,null)):Tc()}function Ad(a){return a?a.slice():null}function Bd(a,b){if(null===a)return null;for(var c=[],d=0;d<a.length;d++)c.push(b(a[d]));return c}function Cd(a,b){var c=a?a.length:0;if(c!=(b?b.length:0))return!1;for(var d=0;d<c;++d)if(a[d]!=b[d])return!1;return!0}function Dd(a,b,c){var d=a?a.length:0;if(d!=(b?b.length:0))return!1;for(var e=0;e<d;++e)if(!c(a[e],b[e]))return!1;return!0} +function Ed(a,b){var c=a?a.length:0;if(c!=(b?b.length:0))return!1;for(var d=0;d<c;d++){var e=a[d],f=b[d];if(e.a!==f.a)return!1;if(e.a.g){if(!e.a.g(e.value,f.value))return!1}else if(12==e.a.b){if(!Cd(e.value,f.value))return!1}else if(e.value!=f.value)return!1}return!0}function Fd(a,b,c,d){if(b&&null!=c&&null!=d){b=Zc(b,c,d-c);b.ca();b.ca();for(c=[];!b.kb();)c.push(a.call(b));Vc(b);return c}return null}function Gd(a,b,c){return a&&null!=b&&null!=c?(a=gd(a,b,c-b),G(a),b=od(a),hd(a),b):null} +function Hd(a,b,c,d,e){if(c&&null!=d&&null!=e){var f=[];for(c=gd(c,d,e-d);G(c);)d=a(),O(c,d,b),f.push(d);hd(c);return f}return null} +function Id(a,b){if(!a)return null;a:{for(var c=0;c<a.length;c++)if(a[c].c==b){a=a[c];break a}a=null}a&&a.a?a.value?a=a.value:null==a||null==a.a||null==a.buffer||null==a.start||null==a.b?a=null:(b=gd(a.buffer,a.start,a.b-a.start),G(b),a.a.a&&a.a.h?(a.value=a.a.a(),O(b,a.value,a.a.h)):a.value=ld(b,a.a.b),hd(b),a.buffer=null,a.start=null,a.b=null,a=a.value):a=null;return a} +function Jd(a,b){var c=a.a,d=jd(a),e=a.b;H(a);a=id(a);var f=null;if(b)for(var g=0;g<b.length;g++){var h=b[g];if(h.c==c){f=h;break}}return vd(c,null,d,e,a,f)};function Ld(a){var b=a;if(a instanceof Array)b=Array(a.length),Md(b,a);else if(a instanceof Object){var c=b={},d;for(d in a)a.hasOwnProperty(d)&&(c[d]=Ld(a[d]))}return b}function Md(a,b){for(var c=0;c<b.length;++c)b.hasOwnProperty(c)&&(a[c]=Ld(b[c]))}function Nd(a,b){a[b]||(a[b]=[]);return a[b]} +function Od(a,b){if(null==a||null==b)return null==a==(null==b);if(a.constructor!=Array&&a.constructor!=Object)throw Error("Invalid object type passed into jsproto.areObjectsEqual()");if(a===b)return!0;if(a.constructor!=b.constructor)return!1;for(var c in a)if(!(c in b&&Pd(a[c],b[c])))return!1;for(var d in b)if(!(d in a))return!1;return!0} +function Pd(a,b){if(a===b||!(!0!==a&&1!==a||!0!==b&&1!==b)||!(!1!==a&&0!==a||!1!==b&&0!==b))return!0;if(a instanceof Object&&b instanceof Object){if(!Od(a,b))return!1}else return!1;return!0}function Qd(a){return Rd(a.replace(/[+/]/g,function(a){return"+"==a?"-":"_"}))}function Sd(a){return Rd(a.replace(/[-_]/g,function(a){return"-"==a?"+":"/"}))}function Rd(a){return a.replace(/[.=]+$/,"")}function Td(a,b,c,d){this.type=a;this.label=b;this.tf=c;this.N=d} +function Ud(a){switch(a){case "d":case "f":case "i":case "j":case "u":case "v":case "x":case "y":case "g":case "h":case "n":case "o":case "e":return 0;case "s":case "z":case "B":return"";case "b":return!1;default:return null}}function Vd(a,b,c){return new Td(a,1,B(b)?b:Ud(a),c)}function Wd(a,b,c){return new Td(a,2,B(b)?b:Ud(a),c)}function Xd(a,b){return new Td(a,3,void 0,b)}var Yd=Vd("d",void 0);function Zd(a){return Vd("f",a)}var $d=Zd();function ae(a){return Vd("i",a)} +var P=ae(),be=Wd("i",void 0),ce=Xd("i"),Q=Vd("u",void 0),de=Wd("u",void 0),ee=Xd("u"),fe=Vd("v",void 0);function ge(a){return Vd("b",a)}var R=ge();function he(a){return Vd("e",a)}var T=he(),ie=Xd("e"),U=Vd("s",void 0),je=Wd("s",void 0),ke=Xd("s"),le=Vd("B",void 0);function V(a,b){return Vd("m",a,b)}function me(){var a=new ne([]),b=oe();return Wd("m",a,b)}function pe(a){return Xd("m",a)}var qe=Wd("x",void 0),re=Xd("x");function se(){}var te=new se,ue=/'/g;se.prototype.b=function(a,b){var c=[];ve(a,b,c);return c.join("&").replace(ue,"%27")};se.prototype.a=function(){throw Error("QueryStringSerializer.deserialize is not implemented");};function ve(a,b,c){for(var d=1;d<b.F.length;++d){var e=b.F[d],f=a[d+b.a];if(e&&null!=f)if(3==e.label)for(var g=0;g<f.length;++g)we(f[g],d,e,c);else we(f,d,e,c)}} +function we(a,b,c,d){if("m"==c.type){var e=d.length;ve(a,c.N,d);d.splice(e,0,[b,"m",d.length-e].join(""))}else"b"==c.type&&(a=a?"1":"0"),a=[b,c.type,encodeURIComponent(a)].join(""),d.push(a)};function W(a){this.data=a||[]}function xe(a,b){return null!=a.data[b]}function ye(a,b,c){a=a.data[b];return null!=a?a:c}function X(a,b,c){return ye(a,b,c||0)}function ze(a,b,c){return ye(a,b,c||"")}function Ae(a,b){var c=a.data[b];c||(c=a.data[b]=[]);return c}function Be(a,b){b in a.data&&delete a.data[b]}function Ce(a,b){return Nd(a.data,b)}function De(a,b){var c=[];Ce(a,b).push(c);return c}function Ee(a,b,c){return Ce(a,b)[c]}function Fe(a,b){return a.data[b]?a.data[b].length:0} +function Ge(a,b){return Od(a.data,b?(b&&b).data:null)}function He(a,b){b=b&&b;a=a.data;b=b?b.data:null;a!==b&&(a.length=0,b&&(a.length=b.length,Md(a,b)))};function Ie(){this.a=null}Ie.prototype.w=function(){return[]};function Je(a){if(a.a)for(var b=0;b<a.a.length;b++)wd(a.a[b]);a.a=null}var Ke=[];Ie.prototype.getExtension=function(a){var b=!1;4<=a&&2147483647>a&&(b=!0);return b?Id(this.a,a):null};function Le(a,b){for(;G(b);){a.a=a.a||[];var c=Jd(b,Ke);a.a.push(c)}};function Me(a){this.data=a||[]}var Ne;F(Me,W);function Oe(){Ne||(Ne={a:-1,F:[]});return Ne};function Pe(a){this.data=a||[]}var Qe;F(Pe,W);function Re(){Qe||(Qe={a:-1,F:[]},Qe.F=[,Wd("y",""),Wd("y",""),V(new Me([]),Oe())]);return Qe};function Se(){this.a=this.b=null}Se.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}null!==this.a&&(b=this.a,a[1]=b);return a};function Te(a){a.b=null;a.a=null}Se.prototype.getExtension=function(){return null};function Ue(a,b){for(;G(b);)switch(b.a){case 1:var c=N(b);a.b=c;break;case 2:c=L(b);a.a=c;break;default:H(b)}};function Ve(){this.b=this.a=null}Ve.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.w();a[0]=b}null!==this.b&&(b=this.b,a[1]=b);return a};function We(a){var b=a.a;b&&Te(b);a.a=null;a.b=null}Ve.prototype.getExtension=function(){return null};function Xe(a,b){for(;G(b);)switch(b.a){case 1:var c=new Se;O(b,c,Ue);a.a=c;break;case 2:c=K(b);a.b=c;break;default:H(b)}};function Ye(){this.a=null}Ye.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.w();a[14]=b}return a};function Ze(a){var b=a.a;b&&We(b);a.a=null}Ye.prototype.getExtension=function(){return null};function $e(a,b){for(;G(b);)switch(b.a){case 15:var c=new Ve;O(b,c,Xe);a.a=c;break;default:H(b)}};function af(a){this.data=a||[]}var bf;F(af,W);function cf(a){this.data=a||[]}var df;F(cf,W);function ef(a){this.data=a||[]}var ff;F(ef,W);function gf(){if(!ff){var a=[];ff={a:-1,F:a};var b=new cf([]);if(!df){var c=df={a:-1,F:[]},d=new af([]);bf||(bf={a:-1,F:[]},bf.F=[,he(4369),U]);c.F=[,V(d,bf),R]}a[15]=V(b,df)}return ff};function hf(){this.a=this.b=this.f=this.c=null}hf.prototype.w=function(){var a=[];if(null!==this.c){var b=this.c;a[0]=b}null!==this.f&&(b=this.f,a[1]=b);null!==this.b&&(b=this.b,b=b.w(),a[14]=b);null!==this.a&&(b=this.a,b=b.w(),a[499]=b);return a}; +function jf(a){var b=new hf;kf(b);b.c=a.c;b.f=a.f;if(a.b){var c=new Ie;var d=a.b;Je(c);c.a=xd(d.a)}else c=null;b.b=c;if(a.a){c=new Ye;d=a.a;Ze(c);if(d.a){a=new Ve;d=d.a;We(a);if(d.a){var e=new Se;var f=d.a;Te(e);e.b=f.b;e.a=f.a}else e=null;a.a=e;a.b=d.b}else a=null;c.a=a}else c=null;b.a=c;return b}function kf(a){a.c=null;a.f=null;var b=a.b;b&&Je(b);a.b=null;(b=a.a)&&Ze(b);a.a=null}hf.prototype.getExtension=function(){return null}; +function lf(a,b){for(;G(b);)switch(b.a){case 1:var c=nd(b);a.c=c;break;case 2:c=nd(b);a.f=c;break;case 15:c=new Ie;O(b,c,Le);a.b=c;break;case 500:c=new Ye;O(b,c,$e);a.a=c;break;default:H(b)}} +function mf(a,b){if(a===b)b=!0;else if(null===a||null===b)b=!1;else{var c;if(c=a.c===b.c&&a.f===b.f){c=a.b;var d=b.b;c=c===d?!0:null===c||null===d?!1:Ed(c.a,d.a)?!0:!1}c&&(a=a.a,c=b.a,a===c?b=!0:null===a||null===c?b=!1:(b=a.a,a=c.a,(c=b===a)||(null===b||null===a?b=0:(c=b.a,d=a.a,b=(c===d?!0:null===c||null===d?!1:c.b!==d.b||c.a!==d.a?!1:!0)&&b.b===a.b),c=b),b=c?!0:!1),c=b);b=c?!0:!1}return b};function ne(a){this.data=a||[]}var nf;F(ne,W);function oe(){if(!nf){var a=[];nf={a:-1,F:a};a[1]=qe;a[2]=qe;a[500]=V(new ef([]),gf());a[15]=V(new Me([]),Oe())}return nf};function of(a){this.data=a||[]}var pf;F(of,W);function qf(){this.a=this.b=null}qf.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;b=b.w();a[0]=b}null!==this.a&&(b=this.a,b=b.w(),a[1]=b);return a};function rf(a){var b=a.b;b&&kf(b);a.b=null;(b=a.a)&&kf(b);a.a=null}qf.prototype.getExtension=function(){return null};function sf(a,b){for(;G(b);)switch(b.a){case 1:var c=new hf;O(b,c,lf);a.b=c;break;case 2:c=new hf;O(b,c,lf);a.a=c;break;default:H(b)}};function tf(a){this.data=a||[]}var uf;F(tf,W);function vf(){this.a=this.b=this.c=null}function wf(){this.b=this.a=null}vf.prototype.w=function(){var a=[];if(null!==this.c){var b=this.c;b=Oc(b,!0);a[0]=b}null!==this.b&&(b=this.b,a[1]=b);null!==this.a&&(b=this.a,a[2]=b);return a};function xf(a){var b=new vf;yf(b);b.c=a.c;b.b=a.b;b.a=a.a;return b}function yf(a){a.c=null;a.b=null;a.a=null}vf.prototype.getExtension=function(){return null}; +function zf(a,b){for(;G(b);)switch(b.a){case 1:var c=qd(b);a.c=c;break;case 2:c=nd(b);a.b=c;break;case 3:c=nd(b);a.a=c;break;default:H(b)}}function Af(a,b){return a===b?!0:null===a||null===b?!1:a.c!==b.c||a.b!==b.b||a.a!==b.a?!1:!0}wf.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.w();a[0]=b}null!==this.b&&(b=this.b,b=Oc(b,!0),a[1]=b);return a};function Bf(a){var b=new wf;Cf(b);b.a=a.a?xf(a.a):null;b.b=a.b;return b}function Cf(a){var b=a.a;b&&yf(b);a.a=null;a.b=null} +wf.prototype.getExtension=function(){return null};function Df(a,b){for(;G(b);)switch(b.a){case 1:var c=new vf;O(b,c,zf);a.a=c;break;case 2:c=qd(b);a.b=c;break;default:H(b)}}function Ef(a,b){return a===b?!0:null===a||null===b?!1:Af(a.a,b.a)&&a.b===b.b?!0:!1};function Ff(){this.f=this.c=this.a=this.b=null}Ff.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;b=b.w();a[0]=b}null!==this.a&&(b=this.a,b=b.w(),a[1]=b);null!==this.c&&(b=this.c,a[2]=b);null!==this.f&&(b=this.f,a[3]=b);return a};function Gf(a){var b=a.b;b&&yf(b);a.b=null;(b=a.a)&&Cf(b);a.a=null;a.c=null;a.f=null}Ff.prototype.getExtension=function(){return null}; +function Hf(a,b){for(;G(b);)switch(b.a){case 1:var c=new vf;O(b,c,zf);a.b=c;break;case 2:c=new wf;O(b,c,Df);a.a=c;break;case 3:c=J(b);a.c=c;break;case 4:c=N(b);a.f=c;break;default:H(b)}}Ff.prototype.ka=function(){return null==this.c?-1:this.c};function If(a){this.data=a||[]}var Jf;F(If,W);function Kf(a){this.data=a||[]}var Lf;F(Kf,W);function Mf(){Jf||(Jf={a:-1,F:[]},Jf.F=[,Wd("j",""),qe,qe]);return Jf}function Nf(){Lf||(Lf={a:-1,F:[]},Lf.F=[,V(new If([]),Mf()),Vd("j","")]);return Lf};function Of(a){this.data=a||[]}var Pf;F(Of,W);Of.prototype.ka=function(){return X(this,2,-1)};function Qf(){this.a=null}Qf.prototype.w=function(){var a=[];null!==this.a&&(a[0]=this.a);return a};Qf.prototype.getExtension=function(){return null};function Rf(a,b){for(;G(b);)switch(b.a){case 1:a.a=N(b);break;default:H(b)}};function Sf(a){this.data=a||[]}var Tf;F(Sf,W);function Uf(){Tf={a:-1,F:[,T]}};function Vf(){this.g=this.h=this.$a=this.ib=this.A=this.va=this.ra=this.D=this.b=this.l=this.Jb=this.f=this.Kb=this.o=this.P=this.C=this.Lb=this.Za=this.Wa=this.Bb=this.Z=this.G=this.H=this.I=this.J=this.Ba=this.Qa=this.Ia=this.c=this.s=this.sb=this.ya=this.jb=this.Ka=this.B=this.La=this.Ja=this.m=this.Sa=this.Ga=this.j=this.u=this.S=this.L=this.T=this.Oa=this.ga=this.ia=this.pa=this.ja=this.Da=this.O=this.Y=this.W=this.ha=this.M=this.U=this.fa=this.V=this.Pa=this.Ra=this.qb=this.a=this.i=this.Ca= +this.v=this.K=this.rb=null}function Wf(){this.b=this.c=this.a=null}function Xf(){this.c=this.f=this.a=this.b=this.g=null}function Yf(){this.b=this.g=this.a=this.f=this.m=this.l=this.j=this.c=this.i=this.h=null}function Zf(){this.a=null}function $f(){this.a=this.b=null}function ag(){this.b=this.a=this.c=null}function bg(){this.c=this.g=this.b=this.a=this.h=this.f=null}function cg(){this.b=this.f=this.c=this.a=null}function dg(){this.f=this.c=this.b=this.a=this.g=null} +function eg(){this.c=this.f=this.h=this.g=this.i=this.j=this.a=this.m=this.l=this.b=this.o=null}function fg(){this.a=this.b=null}function gg(){this.a=this.c=this.b=null}function hg(){this.b=this.c=this.a=null}function ig(){this.b=this.a=null}function jg(){this.a=this.b=this.g=this.f=this.c=null} +function kg(a,b){for(;G(b);)switch(b.a){case 1:var c=N(b);a.rb=c;break;case 2:c=L(b);a.K=c;break;case 3:c=new Wf;O(b,c,lg);a.v=c;break;case 4:c=L(b);a.Ca=c;break;case 5:c=new Yf;O(b,c,mg);a.i=c;break;case 6:c=new Yf;O(b,c,mg);a.a=a.a||[];a.a.push(c);break;case 7:c=K(b);a.qb=c;break;case 8:c=M(b);a.Ra=c;break;case 9:c=M(b);a.Pa=c;break;case 10:c=M(b);a.V=c;break;case 11:c=M(b);a.fa=c;break;case 12:c=M(b);a.U=c;break;case 13:c=M(b);a.M=c;break;case 14:c=M(b);a.ha=c;break;case 15:c=M(b);a.W=c;break; +case 16:c=M(b);a.Y=c;break;case 17:c=M(b);a.O=c;break;case 18:c=M(b);a.Da=c;break;case 19:c=M(b);a.ja=c;break;case 20:c=M(b);a.pa=c;break;case 21:c=L(b);a.ia=c;break;case 22:c=M(b);a.ga=c;break;case 23:c=N(b);a.Oa=c;break;case 24:c=M(b);a.T=c;break;case 25:c=M(b);a.L=c;break;case 26:c=L(b);a.S=c;break;case 27:c=new bg;O(b,c,ng);a.u=c;break;case 28:c=new ag;O(b,c,og);a.j=c;break;case 29:c=N(b);a.Ga=c;break;case 30:c=N(b);a.Sa=c;break;case 31:c=N(b);a.m=a.m||[];a.m.push(c);break;case 32:c=M(b);a.Ja= +c;break;case 33:c=L(b);a.La=c;break;case 34:c=M(b);a.B=c;break;case 35:c=M(b);a.Ka=c;break;case 36:c=M(b);a.jb=c;break;case 37:c=M(b);a.ya=c;break;case 38:c=K(b);a.sb=c;break;case 39:c=N(b);a.s=c;break;case 40:c=new Yf;O(b,c,mg);a.c=a.c||[];a.c.push(c);break;case 41:c=L(b);a.Ia=c;break;case 42:c=L(b);a.Qa=c;break;case 43:c=K(b);a.Ba=c;break;case 44:c=M(b);a.J=c;break;case 45:c=M(b);a.I=c;break;case 46:c=M(b);a.H=c;break;case 47:c=M(b);a.G=c;break;case 48:c=M(b);a.Z=c;break;case 49:c=M(b);a.Bb=c;break; +case 50:c=M(b);a.Wa=c;break;case 51:c=M(b);a.Za=c;break;case 52:c=M(b);a.Lb=c;break;case 53:c=M(b);a.C=c;break;case 54:c=M(b);a.P=c;break;case 55:c=new eg;O(b,c,pg);a.o=c;break;case 56:c=M(b);a.Kb=c;break;case 57:c=new hg;O(b,c,qg);a.f=a.f||[];a.f.push(c);break;case 58:c=M(b);a.Jb=c;break;case 59:c=new fg;O(b,c,rg);a.l=c;break;case 60:c=new gg;O(b,c,sg);a.b=a.b||[];a.b.push(c);break;case 62:c=M(b);a.D=c;break;case 63:c=M(b);a.ra=c;break;case 64:c=M(b);a.va=c;break;case 65:c=new ig;O(b,c,tg);a.A=c; +break;case 66:c=M(b);a.ib=c;break;case 67:c=M(b);a.$a=c;break;case 68:c=new jg;O(b,c,ug);a.h=c;break;case 69:c=new $f;O(b,c,vg);a.g=a.g||[];a.g.push(c);break;default:H(b)}} +Vf.prototype.w=function(){var a=[];if(null!==this.rb){var b=this.rb;a[0]=b}null!==this.K&&(b=this.K,a[1]=b);null!==this.v&&(b=this.v,b=b.w(),a[2]=b);null!==this.Ca&&(b=this.Ca,a[3]=b);null!==this.i&&(b=this.i,b=b.w(),a[4]=b);if(null!==this.a){b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[5]=b}null!==this.qb&&(b=this.qb,a[6]=b);null!==this.Ra&&(b=this.Ra,a[7]=b);null!==this.Pa&&(b=this.Pa,a[8]=b);null!==this.V&&(b=this.V,a[9]=b);null!==this.fa&&(b=this.fa,a[10]=b);null!==this.U&& +(b=this.U,a[11]=b);null!==this.M&&(b=this.M,a[12]=b);null!==this.ha&&(b=this.ha,a[13]=b);null!==this.W&&(b=this.W,a[14]=b);null!==this.Y&&(b=this.Y,a[15]=b);null!==this.O&&(b=this.O,a[16]=b);null!==this.Da&&(b=this.Da,a[17]=b);null!==this.ja&&(b=this.ja,a[18]=b);null!==this.pa&&(b=this.pa,a[19]=b);null!==this.ia&&(b=this.ia,a[20]=b);null!==this.ga&&(b=this.ga,a[21]=b);null!==this.Oa&&(b=this.Oa,a[22]=b);null!==this.T&&(b=this.T,a[23]=b);null!==this.L&&(b=this.L,a[24]=b);null!==this.S&&(b=this.S,a[25]= +b);null!==this.u&&(b=this.u,b=b.w(),a[26]=b);null!==this.j&&(b=this.j,b=b.w(),a[27]=b);null!==this.Ga&&(b=this.Ga,a[28]=b);null!==this.Sa&&(b=this.Sa,a[29]=b);null!==this.m&&(b=this.m,b=b.slice(),a[30]=b);null!==this.Ja&&(b=this.Ja,a[31]=b);null!==this.La&&(b=this.La,a[32]=b);null!==this.B&&(b=this.B,a[33]=b);null!==this.Ka&&(b=this.Ka,a[34]=b);null!==this.jb&&(b=this.jb,a[35]=b);null!==this.ya&&(b=this.ya,a[36]=b);null!==this.sb&&(b=this.sb,a[37]=b);null!==this.s&&(b=this.s,a[38]=b);if(null!==this.c){b= +this.c;b=b.slice();for(c=0;c<b.length;c++)b[c]=b[c].w();a[39]=b}null!==this.Ia&&(b=this.Ia,a[40]=b);null!==this.Qa&&(b=this.Qa,a[41]=b);null!==this.Ba&&(b=this.Ba,a[42]=b);null!==this.J&&(b=this.J,a[43]=b);null!==this.I&&(b=this.I,a[44]=b);null!==this.H&&(b=this.H,a[45]=b);null!==this.G&&(b=this.G,a[46]=b);null!==this.Z&&(b=this.Z,a[47]=b);null!==this.Bb&&(b=this.Bb,a[48]=b);null!==this.Wa&&(b=this.Wa,a[49]=b);null!==this.Za&&(b=this.Za,a[50]=b);null!==this.Lb&&(b=this.Lb,a[51]=b);null!==this.C&& +(b=this.C,a[52]=b);null!==this.P&&(b=this.P,a[53]=b);null!==this.o&&(b=this.o,b=b.w(),a[54]=b);null!==this.Kb&&(b=this.Kb,a[55]=b);if(null!==this.f){b=this.f;b=b.slice();for(c=0;c<b.length;c++)b[c]=b[c].w();a[56]=b}null!==this.Jb&&(b=this.Jb,a[57]=b);null!==this.l&&(b=this.l,b=b.w(),a[58]=b);if(null!==this.b){b=this.b;b=b.slice();for(c=0;c<b.length;c++)b[c]=b[c].w();a[59]=b}null!==this.D&&(b=this.D,a[61]=b);null!==this.ra&&(b=this.ra,a[62]=b);null!==this.va&&(b=this.va,a[63]=b);null!==this.A&&(b= +this.A,b=b.w(),a[64]=b);null!==this.ib&&(b=this.ib,a[65]=b);null!==this.$a&&(b=this.$a,a[66]=b);null!==this.h&&(b=this.h,b=b.w(),a[67]=b);if(null!==this.g){b=this.g;b=b.slice();for(c=0;c<b.length;c++)b[c]=b[c].w();a[68]=b}return a}; +function wg(a,b){xg(a);a.rb=b.rb;a.K=b.K;a.v=b.v?yg(b.v):null;a.Ca=b.Ca;a.i=b.i?zg(b.i):null;a.a=Bd(b.a,Ag);a.qb=b.qb;a.Ra=b.Ra;a.Pa=b.Pa;a.V=b.V;a.fa=b.fa;a.U=b.U;a.M=b.M;a.ha=b.ha;a.W=b.W;a.Y=b.Y;a.O=b.O;a.Da=b.Da;a.ja=b.ja;a.pa=b.pa;a.ia=b.ia;a.ga=b.ga;a.Oa=b.Oa;a.T=b.T;a.L=b.L;a.S=b.S;a.u=b.u?Bg(b.u):null;a.j=b.j?Cg(b.j):null;a.Ga=b.Ga;a.Sa=b.Sa;a.m=Ad(b.m);a.Ja=b.Ja;a.La=b.La;a.B=b.B;a.Ka=b.Ka;a.jb=b.jb;a.ya=b.ya;a.sb=b.sb;a.s=b.s;a.c=Bd(b.c,Ag);a.Ia=b.Ia;a.Qa=b.Qa;a.Ba=b.Ba;a.J=b.J;a.I=b.I; +a.H=b.H;a.G=b.G;a.Z=b.Z;a.Bb=b.Bb;a.Wa=b.Wa;a.Za=b.Za;a.Lb=b.Lb;a.C=b.C;a.P=b.P;a.o=b.o?Dg(b.o):null;a.Kb=b.Kb;a.f=Bd(b.f,Eg);a.Jb=b.Jb;a.l=b.l?Fg(b.l):null;a.b=Bd(b.b,Gg);a.D=b.D;a.ra=b.ra;a.va=b.va;a.A=b.A?Hg(b.A):null;a.ib=b.ib;a.$a=b.$a;a.h=b.h?Ig(b.h):null;a.g=Bd(b.g,Jg)} +function xg(a){a.rb=null;a.K=null;Kg(a.v);a.v=null;a.Ca=null;Lg(a.i);a.i=null;if(a.a)for(var b=0;b<a.a.length;b++)Lg(a.a[b]);a.a=null;a.qb=null;a.Ra=null;a.Pa=null;a.V=null;a.fa=null;a.U=null;a.M=null;a.ha=null;a.W=null;a.Y=null;a.O=null;a.Da=null;a.ja=null;a.pa=null;a.ia=null;a.ga=null;a.Oa=null;a.T=null;a.L=null;a.S=null;Mg(a.u);a.u=null;Ng(a.j);a.j=null;a.Ga=null;a.Sa=null;a.m=null;a.Ja=null;a.La=null;a.B=null;a.Ka=null;a.jb=null;a.ya=null;a.sb=null;a.s=null;if(a.c)for(b=0;b<a.c.length;b++)Lg(a.c[b]); +a.c=null;a.Ia=null;a.Qa=null;a.Ba=null;a.J=null;a.I=null;a.H=null;a.G=null;a.Z=null;a.Bb=null;a.Wa=null;a.Za=null;a.Lb=null;a.C=null;a.P=null;Og(a.o);a.o=null;a.Kb=null;if(a.f)for(b=0;b<a.f.length;b++)Pg(a.f[b]);a.f=null;a.Jb=null;Qg(a.l);a.l=null;if(a.b)for(b=0;b<a.b.length;b++)Rg(a.b[b]);a.b=null;a.D=null;a.ra=null;a.va=null;Sg(a.A);a.A=null;a.ib=null;a.$a=null;Tg(a.h);a.h=null;if(a.g)for(b=0;b<a.g.length;b++)Ug(a.g[b]);a.g=null}Vf.prototype.getExtension=function(){return null}; +function Vg(a,b){kg(a,b)}Vf.prototype.getContext=function(){return null==this.s?0:this.s};Wf.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;a[0]=b}null!==this.c&&(b=this.c,a[1]=b);null!==this.b&&(b=this.b,a[2]=b);return a};function yg(a){var b=new Wf;b.a=null;b.c=null;b.b=null;b.a=a.a;b.c=a.c;b.b=a.b;return b}Wf.prototype.getExtension=function(){return null};function Kg(a){a&&(a.a=null,a.c=null,a.b=null)} +function lg(a,b){for(;G(b);)switch(b.a){case 1:var c=L(b);a.a=c;break;case 2:c=K(b);a.c=c;break;case 3:c=J(b);a.b=c;break;default:H(b)}}Wf.prototype.wa=function(){return null==this.a?"":this.a};Xf.prototype.w=function(){var a=[];if(null!==this.g){var b=this.g;a[0]=b}null!==this.b&&(b=this.b,a[1]=b);null!==this.a&&(b=this.a,a[2]=b);null!==this.f&&(b=this.f,a[3]=b);null!==this.c&&(b=this.c,a[4]=b);return a};function Wg(a){a.g=null;a.b=null;a.a=null;a.f=null;a.c=null}Xf.prototype.getExtension=function(){return null}; +function Xg(a,b){for(;G(b);)switch(b.a){case 1:var c=cd(b.c);a.g=c;break;case 2:c=M(b);a.b=c;break;case 3:c=M(b);a.a=c;break;case 4:c=M(b);a.f=c;break;case 5:c=M(b);a.c=c;break;default:H(b)}} +Yf.prototype.w=function(){var a=[];if(null!==this.h){var b=this.h;a[0]=b}null!==this.i&&(b=this.i,a[1]=b);null!==this.c&&(b=this.c,b=b.slice(),a[2]=b);null!==this.j&&(b=this.j,a[3]=b);null!==this.l&&(b=this.l,a[4]=b);null!==this.m&&(b=this.m,a[5]=b);null!==this.f&&(b=this.f,a[6]=b);if(null!==this.a){b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[7]=b}null!==this.g&&(b=this.g,a[8]=b);null!==this.b&&(b=this.b,b=b.w(),a[9]=b);return a}; +function zg(a){var b=new Yf;Yg(b);b.h=a.h;b.i=a.i;b.c=Ad(a.c);b.j=a.j;b.l=a.l;b.m=a.m;b.f=a.f;b.a=Bd(a.a,Zg);b.g=a.g;if(a.b){var c=new Xf;a=a.b;Wg(c);c.g=a.g;c.b=a.b;c.a=a.a;c.f=a.f;c.c=a.c}else c=null;b.b=c;return b}function Yg(a){a.h=null;a.i=null;a.c=null;a.j=null;a.l=null;a.m=null;a.f=null;if(a.a)for(var b=0;b<a.a.length;b++){var c=a.a[b];c&&(c.a=null)}a.a=null;a.g=null;(b=a.b)&&Wg(b);a.b=null}Yf.prototype.getExtension=function(){return null};function Lg(a){a&&Yg(a)} +function Ag(a){return null===a?null:zg(a)}function mg(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.h=c;break;case 2:c=M(b);a.i=c;break;case 3:c=M(b);a.c=a.c||[];a.c.push(c);break;case 4:c=J(b);a.j=c;break;case 5:c=N(b);a.l=c;break;case 6:c=J(b);a.m=c;break;case 7:c=J(b);a.f=c;break;case 8:c=new Zf;O(b,c,$g);a.a=a.a||[];a.a.push(c);break;case 9:c=N(b);a.g=c;break;case 10:c=new Xf;O(b,c,Xg);a.b=c;break;default:H(b)}} +function ah(a,b){if(a===b)b=!0;else if(null===a||null===b)b=!1;else{var c;if(c=a.h===b.h&&a.i===b.i&&Cd(a.c,b.c)&&a.j===b.j&&a.l===b.l&&a.m===b.m&&a.f===b.f&&Dd(a.a,b.a,bh)&&a.g===b.g)a=a.b,b=b.b,c=a===b?!0:null===a||null===b?!1:a.g!==b.g||a.b!==b.b||a.a!==b.a||a.f!==b.f||a.c!==b.c?!1:!0;b=c?!0:!1}return b}Zf.prototype.w=function(){var a=[];null!==this.a&&(a[0]=this.a);return a};Zf.prototype.getExtension=function(){return null}; +function Zg(a){if(null===a)a=null;else{var b=new Zf;b.a=null;b.a=a.a;a=b}return a}function $g(a,b){for(;G(b);)switch(b.a){case 1:a.a=N(b);break;default:H(b)}}function bh(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a?!1:!0}$f.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}if(null!==this.a){b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[1]=b}return a};function ch(a){a.b=null;if(a.a)for(var b=0;b<a.a.length;b++)Lg(a.a[b]);a.a=null} +$f.prototype.getExtension=function(){return null};function Ug(a){a&&ch(a)}function Jg(a){if(null===a)a=null;else{var b=new $f;ch(b);b.b=a.b;b.a=Bd(a.a,Ag);a=b}return a}function vg(a,b){for(;G(b);)switch(b.a){case 1:var c=L(b);a.b=c;break;case 2:c=new Yf;O(b,c,mg);a.a=a.a||[];a.a.push(c);break;default:H(b)}}function dh(a,b){return a===b?!0:null===a||null===b?!1:a.b===b.b&&Dd(a.a,b.a,ah)?!0:!1} +ag.prototype.w=function(){var a=[];if(null!==this.c){var b=this.c;a[0]=b}null!==this.a&&(b=this.a,a[1]=b);null!==this.b&&(b=this.b,a[2]=b);return a};function Cg(a){var b=new ag;b.c=null;b.a=null;b.b=null;b.c=a.c;b.a=a.a;b.b=a.b;return b}ag.prototype.getExtension=function(){return null};function Ng(a){a&&(a.c=null,a.a=null,a.b=null)}function og(a,b){for(;G(b);)switch(b.a){case 1:var c=K(b);a.c=c;break;case 2:c=K(b);a.a=c;break;case 3:c=K(b);a.b=c;break;default:H(b)}} +bg.prototype.w=function(){var a=[];if(null!==this.f){var b=this.f;a[0]=b}null!==this.h&&(b=this.h,a[1]=b);null!==this.a&&(b=this.a,a[2]=b);null!==this.b&&(b=this.b,a[3]=b);null!==this.g&&(b=this.g,a[4]=b);null!==this.c&&(b=this.c,a[5]=b);return a};function Bg(a){var b=new bg;eh(b);b.f=a.f;b.h=a.h;b.a=a.a;b.b=a.b;b.g=a.g;b.c=a.c;return b}function eh(a){a.f=null;a.h=null;a.a=null;a.b=null;a.g=null;a.c=null}bg.prototype.getExtension=function(){return null};function Mg(a){a&&eh(a)} +function ng(a,b){for(;G(b);)switch(b.a){case 1:var c=K(b);a.f=c;break;case 2:c=M(b);a.h=c;break;case 3:c=M(b);a.a=c;break;case 4:c=M(b);a.b=c;break;case 5:c=M(b);a.g=c;break;case 6:c=M(b);a.c=c;break;default:H(b)}}cg.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;a[0]=b}null!==this.c&&(b=this.c,a[1]=b);null!==this.f&&(b=this.f,a[2]=b);null!==this.b&&(b=this.b,a[3]=b);return a};function fh(a){a.a=null;a.c=null;a.f=null;a.b=null}cg.prototype.getExtension=function(){return null}; +function gh(a,b){for(;G(b);)switch(b.a){case 1:var c=M(b);a.a=c;break;case 2:c=M(b);a.c=c;break;case 3:c=M(b);a.f=c;break;case 4:c=L(b);a.b=c;break;default:H(b)}}dg.prototype.w=function(){var a=[];if(null!==this.g){var b=this.g;a[0]=b}null!==this.a&&(b=this.a,a[1]=b);null!==this.b&&(b=this.b,a[2]=b);null!==this.c&&(b=this.c,a[3]=b);null!==this.f&&(b=this.f,a[4]=b);return a};function hh(a){a.g=null;a.a=null;a.b=null;a.c=null;a.f=null}dg.prototype.getExtension=function(){return null}; +function ih(a){if(null===a)a=null;else{var b=new dg;hh(b);b.g=a.g;b.a=a.a;b.b=a.b;b.c=a.c;b.f=a.f;a=b}return a}function jh(a,b){for(;G(b);)switch(b.a){case 1:var c=K(b);a.g=c;break;case 2:c=K(b);a.a=c;break;case 3:c=K(b);a.b=c;break;case 4:c=M(b);a.c=c;break;case 5:c=M(b);a.f=c;break;default:H(b)}}function kh(a,b){return a===b?!0:null===a||null===b?!1:a.g!==b.g||a.a!==b.a||a.b!==b.b||a.c!==b.c||a.f!==b.f?!1:!0} +eg.prototype.w=function(){var a=[];if(null!==this.o){var b=this.o;a[0]=b}null!==this.b&&(b=this.b,b=b.w(),a[1]=b);null!==this.l&&(b=this.l,a[2]=b);null!==this.m&&(b=this.m,a[3]=b);if(null!==this.a){b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[4]=b}null!==this.j&&(b=this.j,a[5]=b);null!==this.i&&(b=this.i,a[6]=b);null!==this.g&&(b=this.g,a[7]=b);null!==this.h&&(b=this.h,a[8]=b);null!==this.f&&(b=this.f,a[9]=b);null!==this.c&&(b=this.c,a[10]=b);return a}; +function Dg(a){var b=new eg;lh(b);b.o=a.o;if(a.b){var c=new cg;var d=a.b;fh(c);c.a=d.a;c.c=d.c;c.f=d.f;c.b=d.b}else c=null;b.b=c;b.l=a.l;b.m=a.m;b.a=Bd(a.a,ih);b.j=a.j;b.i=a.i;b.g=a.g;b.h=a.h;b.f=a.f;b.c=a.c;return b}function lh(a){a.o=null;var b=a.b;b&&fh(b);a.b=null;a.l=null;a.m=null;if(a.a)for(b=0;b<a.a.length;b++){var c=a.a[b];c&&hh(c)}a.a=null;a.j=null;a.i=null;a.g=null;a.h=null;a.f=null;a.c=null}eg.prototype.getExtension=function(){return null};function Og(a){a&&lh(a)} +function pg(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.o=c;break;case 2:c=new cg;O(b,c,gh);a.b=c;break;case 3:c=K(b);a.l=c;break;case 4:c=J(b);a.m=c;break;case 5:c=new dg;O(b,c,jh);a.a=a.a||[];a.a.push(c);break;case 6:c=J(b);a.j=c;break;case 7:c=J(b);a.i=c;break;case 8:c=J(b);a.g=c;break;case 9:c=J(b);a.h=c;break;case 10:c=J(b);a.f=c;break;case 11:c=J(b);a.c=c;break;default:H(b)}} +function mh(a,b){if(a===b)a=!0;else if(null===a||null===b)a=!1;else{var c;if(c=a.o===b.o){c=a.b;var d=b.b;c=c===d?!0:null===c||null===d?!1:c.a!==d.a||c.c!==d.c||c.f!==d.f||c.b!==d.b?!1:!0}a=c&&a.l===b.l&&a.m===b.m&&Dd(a.a,b.a,kh)&&a.j===b.j&&a.i===b.i&&a.g===b.g&&a.h===b.h&&a.f===b.f&&a.c===b.c?!0:!1}return a}fg.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}null!==this.a&&(b=this.a,a[1]=b);return a};function Fg(a){var b=new fg;b.b=null;b.a=null;b.b=a.b;b.a=a.a;return b} +fg.prototype.getExtension=function(){return null};function Qg(a){a&&(a.b=null,a.a=null)}function rg(a,b){for(;G(b);)switch(b.a){case 1:var c=M(b);a.b=c;break;case 2:c=M(b);a.a=c;break;default:H(b)}}gg.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}null!==this.c&&(b=this.c,a[1]=b);null!==this.a&&(b=this.a,a[2]=b);return a};gg.prototype.getExtension=function(){return null};function Rg(a){a&&(a.b=null,a.c=null,a.a=null)} +function Gg(a){if(null===a)a=null;else{var b=new gg;b.b=null;b.c=null;b.a=null;b.b=a.b;b.c=a.c;b.a=a.a;a=b}return a}function sg(a,b){for(;G(b);)switch(b.a){case 1:var c=N(b);a.b=c;break;case 2:c=L(b);a.c=c;break;case 3:c=J(b);a.a=c;break;default:H(b)}}function nh(a,b){return a===b?!0:null===a||null===b?!1:a.b!==b.b||a.c!==b.c||a.a!==b.a?!1:!0}hg.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.slice();a[0]=b}null!==this.c&&(b=this.c,a[1]=b);null!==this.b&&(b=this.b,a[2]=b);return a}; +hg.prototype.getExtension=function(){return null};function Pg(a){a&&(a.a=null,a.c=null,a.b=null)}function Eg(a){if(null===a)a=null;else{var b=new hg;b.a=null;b.c=null;b.b=null;b.a=Ad(a.a);b.c=a.c;b.b=a.b;a=b}return a}function qg(a,b){for(;G(b);)switch(b.a){case 1:var c=M(b);a.a=a.a||[];a.a.push(c);break;case 2:c=M(b);a.c=c;break;case 3:c=J(b);a.b=c;break;default:H(b)}}function oh(a,b){return a===b?!0:null===a||null===b?!1:Cd(a.a,b.a)&&a.c===b.c&&a.b===b.b?!0:!1} +ig.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;a[0]=b}null!==this.b&&(b=this.b,a[1]=b);return a};function Hg(a){var b=new ig;b.a=null;b.b=null;b.a=a.a;b.b=a.b;return b}ig.prototype.getExtension=function(){return null};function Sg(a){a&&(a.a=null,a.b=null)}function tg(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.a=c;break;case 2:c=J(b);a.b=c;break;default:H(b)}} +jg.prototype.w=function(){var a=[];if(null!==this.c){var b=this.c;a[0]=b}null!==this.f&&(b=this.f,a[1]=b);null!==this.g&&(b=this.g,a[2]=b);null!==this.b&&(b=this.b,a[3]=b);null!==this.a&&(b=this.a,a[4]=b);return a};function Ig(a){var b=new jg;ph(b);b.c=a.c;b.f=a.f;b.g=a.g;b.b=a.b;b.a=a.a;return b}function ph(a){a.c=null;a.f=null;a.g=null;a.b=null;a.a=null}jg.prototype.getExtension=function(){return null};function Tg(a){a&&ph(a)} +function ug(a,b){for(;G(b);)switch(b.a){case 1:var c=M(b);a.c=c;break;case 2:c=M(b);a.f=c;break;case 3:c=M(b);a.g=c;break;case 4:c=M(b);a.b=c;break;case 5:c=M(b);a.a=c;break;default:H(b)}};function qh(a){this.data=a||[]}var rh;F(qh,W);function sh(a){this.data=a||[]}var th;F(sh,W);function uh(a){this.data=a||[]}var vh;F(uh,W);function wh(a){this.data=a||[]}var xh;F(wh,W);var yh,zh;function Ah(a){this.data=a||[]}var Bh;F(Ah,W);function Ch(a){this.data=a||[]}var Dh;F(Ch,W);function Eh(a){this.data=a||[]}var Fh;F(Eh,W);var Gh;function Hh(a){this.data=a||[]}var Ih;F(Hh,W);function Jh(a){this.data=a||[]}var Kh;F(Jh,W);var Lh,Mh;function Nh(a){this.data=a||[]}var Oh;F(Nh,W); +function Ph(a){this.data=a||[]}var Qh;F(Ph,W); +function Rh(){var a=rh={a:-1,F:[]},b=new sh([]);th||(th={a:-1,F:[,U,R,P]});b=V(b,th);var c=V(new wh([]),Sh()),d=pe(Sh()),e=he(22),f=new Ch([]);Dh||(Dh={a:-1,F:[,R,Q,Q,Q,Q,Q]});f=V(f,Dh);var g=new Ah([]);Bh||(Bh={a:-1,F:[,R,R,R]});g=V(g,Bh);var h=he(1),k=he(1),l=pe(Sh()),m=new Hh([]);if(!Ih){var n=Ih={a:-1,F:[]},p=ae(-1),q=new Eh([]);Fh||(Fh={a:-1,F:[,Q,Q,Q,U]});q=V(q,Fh);Gh||(Gh={a:-1,F:[,R,R,R,Q,Q]});n.F=[,p,q,R,P,pe(Gh),ae(-1),P,P,P,P,P]}m=V(m,Ih);Mh||(Mh={a:-1,F:[]},Mh.F=[,ee,Q,ae(-1)]);n=pe(Mh); +p=new Jh([]);Kh||(Kh={a:-1,F:[,Q,Q]});p=V(p,Kh);Lh||(Lh={a:-1,F:[]},Lh.F=[,he(1),U,P]);q=pe(Lh);var t=new Nh([]);Oh||(Oh={a:-1,F:[,P,P]});t=V(t,Oh);var v=new Ph([]);Qh||(Qh={a:-1,F:[,Q,Q,Q,Q,Q]});v=V(v,Qh);zh||(zh={a:-1,F:[]},zh.F=[,U,pe(Sh())]);a.F=[,T,U,b,U,c,d,R,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,U,Q,e,Q,Q,U,f,g,h,k,ie,Q,U,Q,Q,Q,Q,R,T,l,U,U,R,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,Q,m,Q,n,Q,p,q,,Q,Q,Q,t,Q,Q,v,pe(zh)]}qh.prototype.getContext=function(){return ye(this,38,0)};sh.prototype.wa=function(){return ze(this,0)}; +function Sh(){if(!xh){var a=xh={a:-1,F:[]},b=ae(-1);yh||(yh={a:-1,F:[,T]});var c=pe(yh),d=new uh([]);vh||(vh={a:-1,F:[,Yd,Q,Q,Q,Q]});a.F=[,b,Q,ee,P,T,P,P,c,T,V(d,vh)]}return xh};function Th(){this.b=this.a=null}Th.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.slice();a[0]=b}null!==this.b&&(b=this.b,a[1]=b);return a};Th.prototype.getExtension=function(){return null};function Uh(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.a=a.a||[];a.a.push(c);break;case 2:c=J(b);a.b=c;break;default:H(b)}};function Vh(){this.b=this.u=this.a=this.l=this.h=this.c=this.m=this.i=this.j=this.g=this.f=this.s=this.o=null} +Vh.prototype.w=function(){var a=[];if(null!==this.o){var b=this.o;a[0]=b}null!==this.s&&(b=this.s,a[1]=b);null!==this.f&&(b=this.f,a[4]=b);null!==this.g&&(b=this.g,a[5]=b);null!==this.j&&(b=this.j,a[6]=b);null!==this.i&&(b=this.i,a[7]=b);null!==this.m&&(b=this.m,a[8]=b);null!==this.c&&(b=this.c,a[9]=b);null!==this.h&&(b=this.h,a[10]=b);null!==this.l&&(b=this.l,b=Oc(b,!1),a[11]=b);null!==this.a&&(b=this.a,b=b.w(),a[12]=b);null!==this.u&&(b=this.u,a[13]=b);null!==this.b&&(b=this.b,b=b.w(),a[14]=b); +return a};function Wh(a){var b=new Vh;Xh(b);b.o=a.o;b.s=a.s;b.f=a.f;b.g=a.g;b.j=a.j;b.i=a.i;b.m=a.m;b.c=a.c;b.h=a.h;b.l=a.l;b.a=a.a?Bf(a.a):null;b.u=a.u;if(a.b){var c=new Th;a=a.b;c.a=null;c.b=null;c.a=Ad(a.a);c.b=a.b}else c=null;b.b=c;return b}function Xh(a){a.o=null;a.s=null;a.f=null;a.g=null;a.j=null;a.i=null;a.m=null;a.c=null;a.h=null;a.l=null;var b=a.a;b&&Cf(b);a.a=null;a.u=null;if(b=a.b)b.a=null,b.b=null;a.b=null}Vh.prototype.getExtension=function(){return null}; +function Yh(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.o=c;break;case 2:c=J(b);a.s=c;break;case 5:c=J(b);a.f=c;break;case 6:c=J(b);a.g=c;break;case 7:c=J(b);a.j=c;break;case 8:c=J(b);a.i=c;break;case 9:c=J(b);a.m=c;break;case 10:c=K(b);a.c=c;break;case 11:c=J(b);a.h=c;break;case 12:c=pd(b);a.l=c;break;case 13:c=new wf;O(b,c,Df);a.a=c;break;case 14:c=J(b);a.u=c;break;case 15:c=new Th;O(b,c,Uh);a.b=c;break;default:H(b)}} +function Zh(a,b){if(a===b)b=!0;else if(null===a||null===b)b=!1;else{var c;if(c=a.o===b.o&&a.s===b.s&&a.f===b.f&&a.g===b.g&&a.j===b.j&&a.i===b.i&&a.m===b.m&&a.c===b.c&&a.h===b.h&&a.l===b.l&&Ef(a.a,b.a)&&a.u===b.u)a=a.b,b=b.b,c=a===b?!0:null===a||null===b?!1:Cd(a.a,b.a)&&a.b===b.b?!0:!1;b=c?!0:!1}return b};function $h(a){this.data=a||[]}var ai;F($h,W);function bi(a){this.data=a||[]}var ci;F(bi,W);function di(){if(!ci){var a=ci={a:-1,F:[]},b=ae(-1),c=ae(-1),d=ae(-1),e=ae(-1),f=ae(-1),g=Vd("y",""),h=V(new Kf([]),Nf()),k=ae(-1),l=new $h([]);ai||(ai={a:-1,F:[,ce,P]});a.F=[,b,P,,,c,d,P,P,e,R,f,g,h,k,V(l,ai)]}return ci};function ei(){this.g=this.f=this.a=this.c=this.b=null}ei.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;b=b.w();a[0]=b}null!==this.c&&(b=this.c,b=b.w(),a[1]=b);null!==this.a&&(b=this.a,b=b.w(),a[2]=b);null!==this.f&&(b=this.f,a[3]=b);null!==this.g&&(b=this.g,a[4]=b);return a};function fi(a){var b=a.b;b&&yf(b);a.b=null;(b=a.c)&&Xh(b);a.c=null;(b=a.a)&&Cf(b);a.a=null;a.f=null;a.g=null}ei.prototype.getExtension=function(){return null}; +function gi(a,b){for(;G(b);)switch(b.a){case 1:var c=new vf;O(b,c,zf);a.b=c;break;case 2:c=new Vh;O(b,c,Yh);a.c=c;break;case 3:c=new wf;O(b,c,Df);a.a=c;break;case 4:c=L(b);a.f=c;break;case 5:c=L(b);a.g=c;break;default:H(b)}};function hi(){this.a=null}hi.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.w();a[0]=b}return a};function ii(a){var b=a.a;b&&fi(b);a.a=null}hi.prototype.getExtension=function(){return null};function ji(a,b){for(;G(b);)switch(b.a){case 1:var c=new ei;O(b,c,gi);a.a=c;break;default:H(b)}};function ki(a){this.data=a||[]}var li;F(ki,W);function mi(a){this.data=a||[]}var ni;F(mi,W);function oi(){this.a=this.g=this.h=this.c=this.f=this.j=this.l=this.m=this.b=this.i=this.o=null} +oi.prototype.w=function(){var a=[];if(null!==this.o){var b=this.o;a[0]=b}null!==this.i&&(b=this.i,a[2]=b);null!==this.b&&(b=this.b,b=b.slice(),a[3]=b);null!==this.m&&(b=this.m,a[4]=b);null!==this.l&&(b=this.l,a[5]=b);null!==this.j&&(b=this.j,a[6]=b);null!==this.f&&(b=this.f,b=b.w(),a[10]=b);null!==this.c&&(b=this.c,b=b.w(),a[231]=b);null!==this.h&&(b=this.h,b=b.slice(),a[259]=b);null!==this.g&&(b=this.g,b=b.slice(),a[329]=b);return a}; +function pi(a){a.o=null;a.i=null;a.b=null;a.m=null;a.l=null;a.j=null;var b=a.f;b&&Gf(b);a.f=null;(b=a.c)&&ii(b);a.c=null;a.h=null;a.g=null;if(a.a)for(b=0;b<a.a.length;b++)wd(a.a[b]);a.a=null}var qi=[]; +oi.prototype.getExtension=function(a){var b=!1;67<=a&&68>a&&(b=!0);259<=a&&260>a&&(b=!0);270<=a&&271>a&&(b=!0);271<=a&&272>a&&(b=!0);278<=a&&279>a&&(b=!0);234<=a&&235>a&&(b=!0);291<=a&&292>a&&(b=!0);292<=a&&293>a&&(b=!0);294<=a&&295>a&&(b=!0);296<=a&&297>a&&(b=!0);302<=a&&303>a&&(b=!0);304<=a&&305>a&&(b=!0);312<=a&&313>a&&(b=!0);313<=a&&314>a&&(b=!0);317<=a&&318>a&&(b=!0);319<=a&&320>a&&(b=!0);338<=a&&339>a&&(b=!0);355<=a&&356>a&&(b=!0);356<=a&&357>a&&(b=!0);363<=a&&364>a&&(b=!0);368<=a&&369>a&&(b= +!0);return b?Id(this.a,a):null};function ri(a){if(null===a)a=null;else{var b=new oi;pi(b);b.o=a.o;b.i=a.i;b.b=Ad(a.b);b.m=a.m;b.l=a.l;b.j=a.j;if(a.f){var c=new Ff;var d=a.f;Gf(c);c.b=d.b?xf(d.b):null;c.a=d.a?Bf(d.a):null;c.c=d.c;c.f=d.f}else c=null;b.f=c;if(a.c){c=new hi;var e=a.c;ii(c);e.a?(d=new ei,e=e.a,fi(d),d.b=e.b?xf(e.b):null,d.c=e.c?Wh(e.c):null,d.a=e.a?Bf(e.a):null,d.f=e.f,d.g=e.g):d=null;c.a=d}else c=null;b.c=c;b.h=Ad(a.h);b.g=Ad(a.g);b.a=xd(a.a);a=b}return a} +function si(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.o=c;break;case 3:c=J(b);a.i=c;break;case 4:c=J(b);a.b=a.b||[];a.b.push(c);break;case 5:c=L(b);a.m=c;break;case 6:c=N(b);a.l=c;break;case 7:c=J(b);a.j=c;break;case 11:c=new Ff;O(b,c,Hf);a.f=c;break;case 232:c=new hi;O(b,c,ji);a.c=c;break;case 260:c=L(b);a.h=a.h||[];a.h.push(c);break;case 330:c=J(b);a.g=a.g||[];a.g.push(c);break;default:a.a=a.a||[],c=Jd(b,qi),a.a.push(c)}} +function ti(a,b){if(a===b)a=!0;else if(null===a||null===b)a=!1;else{var c;if(c=a.o===b.o&&a.i===b.i&&Cd(a.b,b.b)&&a.m===b.m&&a.l===b.l&&a.j===b.j){c=a.f;var d=b.f;c=c===d?!0:null===c||null===d?!1:Af(c.b,d.b)&&Ef(c.a,d.a)&&c.c===d.c&&c.f===d.f?!0:!1}c&&(d=a.c,c=b.c,d===c?c=!0:null===d||null===c?c=!1:(d=d.a,c=c.a,c=d===c||(null===d||null===c?0:Af(d.b,c.b)&&Zh(d.c,c.c)&&Ef(d.a,c.a)&&d.f===c.f&&d.g===c.g)?!0:!1));a=c&&Cd(a.h,b.h)&&Cd(a.g,b.g)&&Ed(a.a,b.a)?!0:!1}return a};var ui;function vi(){var a=[];ui={a:-1,F:a};a[1]=P;a[3]=ae(-1);a[4]=ce;a[5]=U;a[7]=P;var b=new Of([]);Pf||(Pf={a:-1,F:[]},Pf.F=[,V(new If([]),Mf()),V(new Kf([]),Nf()),ae(-1),T]);a[11]=V(b,Pf);a[330]=ce;a[6]=T;a[260]=ke;b=new mi([]);if(!ni){var c=ni={a:-1,F:[]},d=new ki([]);li||(li={a:-1,F:[]},li.F=[,V(new If([]),Mf()),V(new bi([]),di()),V(new Kf([]),Nf()),U,U]);c.F=[,V(d,li)]}a[232]=V(b,ni)};function wi(){this.b=this.a=null}function xi(){this.b=this.a=null}function yi(){this.a=this.b=null}wi.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;a[2]=b}null!==this.b&&(b=this.b,a[3]=b);return a};function zi(a){var b=new wi;Ai(b);b.a=a.a;b.b=a.b;return b}function Ai(a){a.a=null;a.b=null}wi.prototype.getExtension=function(){return null};function Bi(a,b){for(;G(b);)switch(b.a){case 3:var c=cd(b.c);a.a=c;break;case 4:c=cd(b.c);a.b=c;break;default:H(b)}} +function Ci(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a||a.b!==b.b?!1:!0}xi.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;a[0]=b}null!==this.b&&(b=this.b,a[1]=b);return a};function Di(a){var b=new xi;b.a=null;b.b=null;b.a=a.a;b.b=a.b;return b}xi.prototype.getExtension=function(){return null};function Ei(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.a=c;break;case 2:c=J(b);a.b=c;break;default:H(b)}} +function Fi(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a||a.b!==b.b?!1:!0}yi.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;b=b.w();a[0]=b}null!==this.a&&(b=this.a,b=b.w(),a[1]=b);return a};function Gi(a){var b=a.b;b&&(b.a=null,b.b=null);a.b=null;if(b=a.a)b.a=null,b.b=null;a.a=null}yi.prototype.getExtension=function(){return null};function Hi(a){if(null===a)a=null;else{var b=new yi;Gi(b);b.b=a.b?Di(a.b):null;b.a=a.a?Di(a.a):null;a=b}return a} +function Ii(a,b){for(;G(b);)switch(b.a){case 1:var c=new xi;O(b,c,Ei);a.b=c;break;case 2:c=new xi;O(b,c,Ei);a.a=c;break;default:H(b)}}function Ji(a,b){return a===b?!0:null===a||null===b?!1:Fi(a.b,b.b)&&Fi(a.a,b.a)?!0:!1};function Ki(){this.c=this.a=this.g=this.f=this.b=null}Ki.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}null!==this.f&&(b=this.f,a[1]=b);null!==this.g&&(b=this.g,a[2]=b);null!==this.a&&(b=this.a,a[3]=b);null!==this.c&&(b=this.c,a[4]=b);return a};function Li(a){var b=new Ki;Mi(b);b.b=a.b;b.f=a.f;b.g=a.g;b.a=a.a;b.c=a.c;return b}function Mi(a){a.b=null;a.f=null;a.g=null;a.a=null;a.c=null}Ki.prototype.getExtension=function(){return null}; +function Ni(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.b=c;break;case 2:c=J(b);a.f=c;break;case 3:c=J(b);a.g=c;break;case 4:c=N(b);a.a=c;break;case 5:c=L(b);a.c=c;break;default:H(b)}}function Oi(a,b){return a===b?!0:null===a||null===b?!1:a.b!==b.b||a.f!==b.f||a.g!==b.g||a.a!==b.a||a.c!==b.c?!1:!0};function Pi(){this.f=this.c=this.b=this.a=null}function Qi(){this.b=this.c=this.a=null}function Ri(){this.b=this.c=this.a=null}function Si(){this.a=this.b=null}Pi.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.w();a[0]=b}null!==this.b&&(b=this.b,b=b.w(),a[1]=b);null!==this.c&&(b=this.c,b=b.w(),a[2]=b);null!==this.f&&(b=this.f,a[3]=b);return a}; +function Ti(a){var b=new Pi;Ui(b);if(a.a){var c=a.a;var d=new Qi;d.a=null;d.c=null;d.b=null;d.a=c.a;d.c=c.c;d.b=c.b;c=d}else c=null;b.a=c;a.b?(c=a.b,d=new Ri,d.a=null,d.c=null,d.b=null,d.a=c.a,d.c=c.c,d.b=c.b,c=d):c=null;b.b=c;a.c?(c=a.c,d=new Si,d.b=null,d.a=null,d.b=c.b,d.a=c.a,c=d):c=null;b.c=c;b.f=a.f;return b}function Ui(a){var b=a.a;b&&(b.a=null,b.c=null,b.b=null);a.a=null;if(b=a.b)b.a=null,b.c=null,b.b=null;a.b=null;if(b=a.c)b.b=null,b.a=null;a.c=null;a.f=null}Pi.prototype.getExtension=function(){return null}; +function Vi(a,b){for(;G(b);)switch(b.a){case 1:var c=new Qi;O(b,c,Wi);a.a=c;break;case 2:c=new Ri;O(b,c,Xi);a.b=c;break;case 3:c=new Si;O(b,c,Yi);a.c=c;break;case 4:c=md(b);a.f=c;break;default:H(b)}} +function Zi(a,b){if(a===b)a=!0;else if(null===a||null===b)a=!1;else{var c=a.a,d=b.a;if(c=c===d?!0:null===c||null===d?!1:c.a!==d.a||c.c!==d.c||c.b!==d.b?!1:!0)c=a.b,d=b.b,c=c===d?!0:null===c||null===d?!1:c.a!==d.a||c.c!==d.c||c.b!==d.b?!1:!0;c&&(c=a.c,d=b.c,c=c===d?!0:null===c||null===d?!1:c.b!==d.b||c.a!==d.a?!1:!0);a=c&&a.f===b.f?!0:!1}return a}Qi.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;a[0]=b}null!==this.c&&(b=this.c,a[1]=b);null!==this.b&&(b=this.b,a[2]=b);return a}; +Qi.prototype.getExtension=function(){return null};function Wi(a,b){for(;G(b);)switch(b.a){case 1:var c=cd(b.c);a.a=c;break;case 2:c=cd(b.c);a.c=c;break;case 3:c=cd(b.c);a.b=c;break;default:H(b)}}Qi.prototype.ud=function(){return null==this.a?0:this.a};Ri.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;a[0]=b}null!==this.c&&(b=this.c,a[1]=b);null!==this.b&&(b=this.b,a[2]=b);return a};Ri.prototype.getExtension=function(){return null}; +function Xi(a,b){for(;G(b);)switch(b.a){case 1:var c=md(b);a.a=c;break;case 2:c=md(b);a.c=c;break;case 3:c=md(b);a.b=c;break;default:H(b)}}Si.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}null!==this.a&&(b=this.a,a[1]=b);return a};Si.prototype.getExtension=function(){return null};function Yi(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.b=c;break;case 2:c=J(b);a.a=c;break;default:H(b)}};function $i(){this.v=this.u=this.s=this.a=this.m=this.j=this.g=this.i=this.h=this.f=this.b=this.c=this.o=this.l=null} +$i.prototype.w=function(){var a=[];if(null!==this.l){var b=this.l;a[0]=b}null!==this.o&&(b=this.o,a[1]=b);null!==this.c&&(b=this.c,b=b.w(),a[2]=b);null!==this.b&&(b=this.b,b=b.w(),a[3]=b);null!==this.f&&(b=this.f,a[4]=b);null!==this.h&&(b=this.h,a[5]=b);null!==this.i&&(b=this.i,a[6]=b);null!==this.g&&(b=this.g,a[8]=b);null!==this.j&&(b=this.j,a[9]=b);null!==this.m&&(b=this.m,a[10]=b);aj(this);null!==this.a&&(b=this.a,b=Dc(b),a[11]=b);return a}; +function bj(a){var b=new $i;cj(b);b.l=a.l;b.o=a.o;b.c=a.c?Ti(a.c):null;b.b=a.b?zi(a.b):null;b.f=a.f;b.h=a.h;b.i=a.i;b.g=a.g;b.j=a.j;b.m=a.m;b.a=a.a?new Uint8Array(a.a):null;b.s=a.s;b.u=a.u;b.v=a.v;return b}function cj(a){a.l=null;a.o=null;var b=a.c;b&&Ui(b);a.c=null;(b=a.b)&&Ai(b);a.b=null;a.f=null;a.h=null;a.i=null;a.g=null;a.j=null;a.m=null;a.a=null;a.s=null;a.u=null}$i.prototype.getExtension=function(){return null}; +function dj(a,b){for(a.v=jd(b);G(b);)switch(b.a){case 1:var c=L(b);a.l=c;break;case 2:c=L(b);a.o=c;break;case 3:c=new Pi;O(b,c,Vi);a.c=c;break;case 4:c=new wi;O(b,c,Bi);a.b=c;break;case 5:c=N(b);a.f=c;break;case 6:c=K(b);a.h=c;break;case 7:c=K(b);a.i=c;break;case 9:c=N(b);a.g=c;break;case 10:c=J(b);a.j=c;break;case 11:c=L(b);a.m=c;break;case 12:null===a.s&&(a.s=b.b);kd(b);a.u=id(b);break;default:H(b)}} +function ej(a,b){a===b?a=!0:null===a||null===b?a=!1:a.l===b.l&&a.o===b.o&&Zi(a.c,b.c)&&Ci(a.b,b.b)&&a.f===b.f&&a.h===b.h&&a.i===b.i&&a.g===b.g&&a.j===b.j&&a.m===b.m?(aj(a),a=Cd(a.a,b.a)?!0:!1):a=!1;return a}function aj(a){null!=a.s&&null==a.a&&(a.a=Gd(a.v,a.s,a.u))};function fj(){this.b=this.a=null}fj.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[0]=b}null!==this.b&&(b=this.b,a[1]=b);return a};function gj(a){if(a.a)for(var b=0;b<a.a.length;b++){var c=a.a[b];c&&Gi(c)}a.a=null;a.b=null}fj.prototype.getExtension=function(){return null};function hj(a,b){for(;G(b);)switch(b.a){case 1:var c=new yi;O(b,c,Ii);a.a=a.a||[];a.a.push(c);break;case 2:c=K(b);a.b=c;break;default:H(b)}};function ij(){this.u=this.f=this.g=this.v=this.c=this.K=this.L=this.W=this.U=this.s=this.J=this.V=this.l=this.j=this.P=this.S=this.m=this.h=this.M=this.O=this.B=this.C=this.D=this.i=this.H=this.G=this.I=this.b=this.a=this.T=this.A=this.o=null} +ij.prototype.w=function(){var a=[];if(null!==this.o){var b=this.o;a[0]=b}null!==this.A&&(b=this.A,a[1]=b);null!==this.T&&(b=this.T,a[2]=b);null!==this.a&&(b=this.a,a[3]=b);null!==this.b&&(b=this.b,a[6]=b);null!==this.I&&(b=this.I,a[8]=b);null!==this.G&&(b=this.G,a[16]=b);null!==this.H&&(b=this.H,a[17]=b);null!==this.i&&(b=this.i,a[19]=b);null!==this.D&&(b=this.D,a[22]=b);null!==this.C&&(b=this.C,a[23]=b);null!==this.B&&(b=this.B,a[24]=b);null!==this.O&&(b=this.O,a[25]=b);null!==this.M&&(b=this.M, +a[26]=b);null!==this.h&&(b=this.h,a[27]=b);null!==this.m&&(b=this.m,a[28]=b);null!==this.S&&(b=this.S,a[31]=b);null!==this.P&&(b=this.P,a[32]=b);null!==this.j&&(b=this.j,a[38]=b);null!==this.l&&(b=this.l,a[39]=b);null!==this.V&&(b=this.V,a[40]=b);null!==this.J&&(b=this.J,a[41]=b);null!==this.s&&(b=this.s,a[42]=b);null!==this.U&&(b=this.U,a[43]=b);null!==this.W&&(b=this.W,a[44]=b);null!==this.L&&(b=this.L,a[45]=b);null!==this.K&&(b=this.K,a[46]=b);null!==this.c&&(b=this.c,a[47]=b);null!==this.v&&(b= +this.v,a[48]=b);null!==this.g&&(b=this.g,a[49]=b);null!==this.f&&(b=this.f,a[50]=b);null!==this.u&&(b=this.u,a[51]=b);return a};function jj(a,b){kj(a);a.o=b.o;a.A=b.A;a.T=b.T;a.a=b.a;a.b=b.b;a.I=b.I;a.G=b.G;a.H=b.H;a.i=b.i;a.D=b.D;a.C=b.C;a.B=b.B;a.O=b.O;a.M=b.M;a.h=b.h;a.m=b.m;a.S=b.S;a.P=b.P;a.j=b.j;a.l=b.l;a.V=b.V;a.J=b.J;a.s=b.s;a.U=b.U;a.W=b.W;a.L=b.L;a.K=b.K;a.c=b.c;a.v=b.v;a.g=b.g;a.f=b.f;a.u=b.u} +function kj(a){a.o=null;a.A=null;a.T=null;a.a=null;a.b=null;a.I=null;a.G=null;a.H=null;a.i=null;a.D=null;a.C=null;a.B=null;a.O=null;a.M=null;a.h=null;a.m=null;a.S=null;a.P=null;a.j=null;a.l=null;a.V=null;a.J=null;a.s=null;a.U=null;a.W=null;a.L=null;a.K=null;a.c=null;a.v=null;a.g=null;a.f=null;a.u=null}ij.prototype.getExtension=function(){return null}; +function lj(a,b){for(;G(b);)switch(b.a){case 1:var c=K(b);a.o=c;break;case 2:c=J(b);a.A=c;break;case 3:c=J(b);a.T=c;break;case 4:c=K(b);a.a=c;break;case 7:c=J(b);a.b=c;break;case 9:c=L(b);a.I=c;break;case 17:c=K(b);a.G=c;break;case 18:c=K(b);a.H=c;break;case 20:c=J(b);a.i=c;break;case 23:c=K(b);a.D=c;break;case 24:c=J(b);a.C=c;break;case 25:c=K(b);a.B=c;break;case 26:c=J(b);a.O=c;break;case 27:c=J(b);a.M=c;break;case 28:c=cd(b.c);a.h=c;break;case 29:c=K(b);a.m=c;break;case 32:c=J(b);a.S=c;break;case 33:c= +J(b);a.P=c;break;case 39:c=J(b);a.j=c;break;case 40:c=J(b);a.l=c;break;case 41:c=J(b);a.V=c;break;case 42:c=K(b);a.J=c;break;case 43:c=J(b);a.s=c;break;case 44:c=K(b);a.U=c;break;case 45:c=K(b);a.W=c;break;case 46:c=J(b);a.L=c;break;case 47:c=J(b);a.K=c;break;case 48:c=K(b);a.c=c;break;case 49:c=K(b);a.v=c;break;case 50:c=K(b);a.g=c;break;case 51:c=K(b);a.f=c;break;case 52:c=L(b);a.u=c;break;default:H(b)}};function mj(){this.a=this.b=this.c=this.f=null}mj.prototype.w=function(){var a=[];if(null!==this.f){var b=this.f;a[0]=b}null!==this.c&&(b=this.c,a[1]=b);null!==this.b&&(b=this.b,a[2]=b);null!==this.a&&(b=this.a,a[3]=b);return a};function nj(a){a.f=null;a.c=null;a.b=null;a.a=null}mj.prototype.getExtension=function(){return null};function oj(a,b){for(;G(b);)switch(b.a){case 1:var c=L(b);a.f=c;break;case 2:c=md(b);a.c=c;break;case 3:c=L(b);a.b=c;break;case 4:c=L(b);a.a=c;break;default:H(b)}};function pj(){this.f=this.a=this.g=this.s=this.h=this.v=this.i=this.o=this.b=this.m=this.l=this.j=this.c=this.u=this.A=null}function sj(){this.g=this.f=this.c=this.a=this.b=null}function tj(){this.a=this.b=null}function uj(){this.b=this.c=this.a=null}function vj(){this.S=this.u=this.J=this.T=this.P=this.a=this.D=this.I=this.L=this.V=this.A=this.C=this.B=this.l=this.i=this.f=this.H=this.g=this.G=this.M=this.O=this.h=this.U=this.v=this.K=this.s=this.c=this.o=this.m=this.b=this.j=null} +function wj(){this.a=null}function xj(){this.l=this.h=this.b=this.j=this.i=this.a=this.f=this.c=this.g=null}function yj(){this.f=this.j=this.a=this.i=this.c=this.b=this.g=this.h=null}function zj(){this.c=this.b=this.f=this.a=null}function Aj(){this.h=this.c=this.a=this.g=this.f=this.b=this.o=this.i=this.j=this.l=this.m=null}function Bj(){this.a=null}function Cj(){this.a=this.b=null}function Dj(){this.a=this.b=null}function Ej(){this.l=this.f=this.i=this.g=this.a=this.h=this.j=this.c=this.b=null} +function Fj(){this.a=null}function Gj(){this.b=this.a=null}function Hj(){this.g=this.a=this.b=this.f=this.h=this.c=null} +pj.prototype.w=function(){var a=[];if(null!==this.A){var b=this.A;a[0]=b}null!==this.u&&(b=this.u,a[1]=b);null!==this.c&&(b=this.c,b=b.w(),a[2]=b);null!==this.j&&(b=this.j,a[3]=b);null!==this.l&&(b=this.l,a[4]=b);null!==this.m&&(b=this.m,a[5]=b);null!==this.b&&(b=this.b,b=b.w(),a[6]=b);null!==this.o&&(b=this.o,a[7]=b);null!==this.i&&(b=this.i,a[8]=b);null!==this.v&&(b=this.v,a[10]=b);null!==this.h&&(b=this.h,a[11]=b);null!==this.s&&(b=this.s,a[12]=b);null!==this.g&&(b=this.g,a[13]=b);null!==this.a&& +(b=this.a,b=b.w(),a[15]=b);null!==this.f&&(b=this.f,a[16]=b);return a};function Ij(a){var b=new pj;Jj(b);b.A=a.A;b.u=a.u;b.c=a.c?zi(a.c):null;b.j=a.j;b.l=a.l;b.m=a.m;if(a.b){var c=new mj;var d=a.b;nj(c);c.f=d.f;c.c=d.c;c.b=d.b;c.a=d.a}else c=null;b.b=c;b.o=a.o;b.i=a.i;b.v=a.v;b.h=a.h;b.s=a.s;b.g=a.g;if(a.a){d=a.a;c=new Fj;Kj(c);if(d.a){d=d.a;var e=new Gj;Lj(e);e.a=d.a?Ij(d.a):null;e.b=d.b;d=e}else d=null;c.a=d}else c=null;b.a=c;b.f=a.f;return b} +function Jj(a){a.A=null;a.u=null;var b=a.c;b&&Ai(b);a.c=null;a.j=null;a.l=null;a.m=null;(b=a.b)&&nj(b);a.b=null;a.o=null;a.i=null;a.v=null;a.h=null;a.s=null;a.g=null;(b=a.a)&&Kj(b);a.a=null;a.f=null}pj.prototype.getExtension=function(){return null};function Mj(a){return null===a?null:Ij(a)} +function Nj(a,b){for(;G(b);)switch(b.a){case 1:var c=L(b);a.A=c;break;case 2:c=L(b);a.u=c;break;case 3:c=new wi;O(b,c,Bi);a.c=c;break;case 4:c=L(b);a.j=c;break;case 5:c=N(b);a.l=c;break;case 6:c=N(b);a.m=c;break;case 7:c=new mj;O(b,c,oj);a.b=c;break;case 8:c=L(b);a.o=c;break;case 9:c=K(b);a.i=c;break;case 11:c=K(b);a.v=c;break;case 12:c=L(b);a.h=c;break;case 13:c=L(b);a.s=c;break;case 14:c=L(b);a.g=c;break;case 16:c=new Fj;O(b,c,Oj);a.a=c;break;case 17:c=J(b);a.f=c;break;default:H(b)}} +function Pj(a,b){if(a===b)a=!0;else if(null===a||null===b)a=!1;else{var c;if(c=a.A===b.A&&a.u===b.u&&Ci(a.c,b.c)&&a.j===b.j&&a.l===b.l&&a.m===b.m){c=a.b;var d=b.b;c=c===d?!0:null===c||null===d?!1:c.f!==d.f||c.c!==d.c||c.b!==d.b||c.a!==d.a?!1:!0}if(c=c&&a.o===b.o&&a.i===b.i&&a.v===b.v&&a.h===b.h&&a.s===b.s&&a.g===b.g)d=a.a,c=b.a,d===c?c=!0:null===d||null===c?c=!1:(d=d.a,c=c.a,c=d===c||(null===d||null===c?0:Pj(d.a,c.a)&&d.b===c.b)?!0:!1);a=c&&a.f===b.f?!0:!1}return a} +sj.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}null!==this.a&&(b=this.a,b=b.w(),a[1]=b);null!==this.c&&(b=this.c,a[2]=b);null!==this.f&&(b=this.f,a[3]=b);null!==this.g&&(b=this.g,a[4]=b);return a};function Qj(a){a.b=null;var b=a.a;b&&Ai(b);a.a=null;a.c=null;a.f=null;a.g=null}sj.prototype.getExtension=function(){return null};function Rj(a){if(null===a)a=null;else{var b=new sj;Qj(b);b.b=a.b;b.a=a.a?zi(a.a):null;b.c=a.c;b.f=a.f;b.g=a.g;a=b}return a} +function Sj(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.b=c;break;case 2:c=new wi;O(b,c,Bi);a.a=c;break;case 3:c=L(b);a.c=c;break;case 4:c=md(b);a.f=c;break;case 5:c=K(b);a.g=c;break;default:H(b)}}function Tj(a,b){return a===b?!0:null===a||null===b?!1:a.b===b.b&&Ci(a.a,b.a)&&a.c===b.c&&a.f===b.f&&a.g===b.g?!0:!1}tj.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}null!==this.a&&(b=this.a,a[1]=b);return a};function Uj(a,b){a.b=null;a.a=null;a.b=b.b;a.a=b.a} +tj.prototype.getExtension=function(){return null};function Vj(a,b){for(;G(b);)switch(b.a){case 1:var c=N(b);a.b=c;break;case 2:c=K(b);a.a=c;break;default:H(b)}}uj.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;a[0]=b}null!==this.c&&(b=this.c,a[1]=b);null!==this.b&&(b=this.b,b=Oc(b,!0),a[2]=b);return a};function Wj(a,b){a.a=null;a.c=null;a.b=null;a.a=b.a;a.c=b.c;a.b=b.b}uj.prototype.getExtension=function(){return null}; +function Xj(a,b){for(;G(b);)switch(b.a){case 1:var c=N(b);a.a=c;break;case 2:c=N(b);a.c=c;break;case 3:c=qd(b);a.b=c;break;default:H(b)}} +vj.prototype.w=function(){var a=[];if(null!==this.j){var b=this.j;b=b.w();a[0]=b}null!==this.b&&(b=this.b,b=b.w(),a[1]=b);null!==this.m&&(b=this.m,a[2]=b);null!==this.o&&(b=this.o,a[3]=b);null!==this.c&&(b=this.c,b=b.w(),a[5]=b);null!==this.s&&(b=this.s,a[6]=b);null!==this.K&&(b=this.K,a[7]=b);null!==this.v&&(b=this.v,a[8]=b);null!==this.U&&(b=this.U,a[9]=b);null!==this.h&&(b=this.h,b=b.w(),a[10]=b);null!==this.O&&(b=this.O,a[11]=b);null!==this.M&&(b=this.M,a[12]=b);null!==this.G&&(b=this.G,a[13]= +b);null!==this.g&&(b=this.g,b=b.slice(),a[14]=b);null!==this.H&&(b=this.H,a[15]=b);null!==this.f&&(b=this.f,b=b.w(),a[16]=b);null!==this.i&&(b=this.i,b=b.w(),a[18]=b);null!==this.l&&(b=this.l,b=b.w(),a[19]=b);null!==this.B&&(b=this.B,a[24]=b);null!==this.C&&(b=this.C,a[25]=b);null!==this.A&&(b=this.A,a[30]=b);null!==this.V&&(b=this.V,a[32]=b);null!==this.L&&(b=this.L,a[33]=b);null!==this.I&&(b=this.I,a[34]=b);null!==this.D&&(b=this.D,a[36]=b);if(null!==this.a){b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]= +b[c].w();a[37]=b}null!==this.P&&(b=this.P,a[38]=b);null!==this.T&&(b=this.T,a[39]=b);null!==this.J&&(b=this.J,a[40]=b);null!==this.u&&(b=this.u,a[41]=b);null!==this.S&&(b=this.S,a[42]=b);return a}; +function Yj(a,b){Zj(a);if(b.j){var c=b.j;var d=new Aj;ak(d);d.m=c.m;d.l=c.l;d.j=c.j;d.i=c.i;d.o=c.o;d.b=Ad(c.b);d.f=c.f;d.g=c.g;d.a=Bd(c.a,bk);if(c.c){var e=c.c;var f=new Cj;ck(f);f.b=e.b;f.a=e.a?dk(e.a):null;e=f}else e=null;d.c=e;d.h=c.h;c=d}else c=null;a.j=c;b.b?(c=b.b,d=new Ej,ek(d),d.b=c.b,d.c=c.c,d.j=c.j,d.h=c.h,c.a?(e=new xj,fk(e,c.a)):e=null,d.a=e,d.g=c.g,d.i=c.i,d.f=c.f,d.l=c.l,c=d):c=null;a.b=c;a.m=b.m;a.o=b.o;b.c?(c=new ij,jj(c,b.c)):c=null;a.c=c;a.s=b.s;a.K=b.K;a.v=b.v;a.U=b.U;b.h?(c=new tj, +Uj(c,b.h)):c=null;a.h=c;a.O=b.O;a.M=b.M;a.G=b.G;a.g=Ad(b.g);a.H=b.H;b.f?(c=b.f,d=new zj,gk(d),d.a=Ad(c.a),d.f=c.f,d.b=Ad(c.b),d.c=c.c,c=d):c=null;a.f=c;b.i?(c=new uj,Wj(c,b.i)):c=null;a.i=c;b.l?(c=b.l,d=new yj,hk(d),d.h=c.h,d.g=c.g,d.b=c.b,d.c=c.c,d.i=c.i,d.a=c.a,d.j=c.j,d.f=c.f,c=d):c=null;a.l=c;a.B=b.B;a.C=b.C;a.A=b.A;a.V=b.V;a.L=b.L;a.I=b.I;a.D=b.D;a.a=Bd(b.a,ik);a.P=b.P;a.T=b.T;a.J=b.J;a.u=b.u;a.S=b.S} +function Zj(a){var b=a.j;b&&ak(b);a.j=null;(b=a.b)&&ek(b);a.b=null;a.m=null;a.o=null;(b=a.c)&&kj(b);a.c=null;a.s=null;a.K=null;a.v=null;a.U=null;if(b=a.h)b.b=null,b.a=null;a.h=null;a.O=null;a.M=null;a.G=null;a.g=null;a.H=null;(b=a.f)&&gk(b);a.f=null;if(b=a.i)b.a=null,b.c=null,b.b=null;a.i=null;(b=a.l)&&hk(b);a.l=null;a.B=null;a.C=null;a.A=null;a.V=null;a.L=null;a.I=null;a.D=null;if(a.a)for(b=0;b<a.a.length;b++){var c=a.a[b];c&&(c.a=null)}a.a=null;a.P=null;a.T=null;a.J=null;a.u=null;a.S=null} +vj.prototype.getExtension=function(){return null}; +function jk(a,b){for(;G(b);)switch(b.a){case 1:var c=new Aj;O(b,c,kk);a.j=c;break;case 2:c=new Ej;O(b,c,lk);a.b=c;break;case 3:c=K(b);a.m=c;break;case 4:c=K(b);a.o=c;break;case 6:c=new ij;O(b,c,lj);a.c=c;break;case 7:c=K(b);a.s=c;break;case 8:c=K(b);a.K=c;break;case 9:c=N(b);a.v=c;break;case 10:c=K(b);a.U=c;break;case 11:c=new tj;O(b,c,Vj);a.h=c;break;case 12:c=K(b);a.O=c;break;case 13:c=K(b);a.M=c;break;case 14:c=K(b);a.G=c;break;case 15:c=J(b);a.g=a.g||[];a.g.push(c);break;case 16:c=K(b);a.H=c; +break;case 17:c=new zj;O(b,c,mk);a.f=c;break;case 19:c=new uj;O(b,c,Xj);a.i=c;break;case 20:c=new yj;O(b,c,nk);a.l=c;break;case 25:c=K(b);a.B=c;break;case 26:c=K(b);a.C=c;break;case 31:c=K(b);a.A=c;break;case 33:c=K(b);a.V=c;break;case 34:c=K(b);a.L=c;break;case 35:c=K(b);a.I=c;break;case 37:c=K(b);a.D=c;break;case 38:c=new wj;O(b,c,ok);a.a=a.a||[];a.a.push(c);break;case 39:c=K(b);a.P=c;break;case 40:c=K(b);a.T=c;break;case 41:c=K(b);a.J=c;break;case 42:c=K(b);a.u=c;break;case 43:c=J(b);a.S=c;break; +default:H(b)}}wj.prototype.w=function(){var a=[];null!==this.a&&(a[0]=this.a);return a};wj.prototype.getExtension=function(){return null};function ik(a){if(null===a)a=null;else{var b=new wj;b.a=null;b.a=a.a;a=b}return a}function ok(a,b){for(;G(b);)switch(b.a){case 1:a.a=J(b);break;default:H(b)}}function pk(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a?!1:!0} +xj.prototype.w=function(){var a=[];if(null!==this.g){var b=this.g;a[1]=b}null!==this.c&&(b=this.c,a[2]=b);null!==this.f&&(b=this.f,a[3]=b);null!==this.a&&(b=this.a,a[4]=b);null!==this.i&&(b=this.i,a[5]=b);null!==this.j&&(b=this.j,a[6]=b);null!==this.b&&(b=this.b,a[8]=b);null!==this.h&&(b=this.h,a[9]=b);return a};function fk(a,b){qk(a);a.g=b.g;a.c=b.c;a.f=b.f;a.a=b.a;a.i=b.i;a.j=b.j;a.b=b.b;a.h=b.h;a.l=b.l}function qk(a){a.g=null;a.c=null;a.f=null;a.a=null;a.i=null;a.j=null;a.b=null;a.h=null} +xj.prototype.getExtension=function(){return null};function rk(a,b){for(a.l=jd(b);G(b);)switch(b.a){case 2:var c=K(b);a.g=c;break;case 3:c=K(b);a.c=c;break;case 4:c=K(b);a.f=c;break;case 5:c=K(b);a.a=c;break;case 6:c=N(b);a.i=c;break;case 7:c=N(b);a.j=c;break;case 9:c=K(b);a.b=c;break;case 10:c=N(b);a.h=c;break;default:H(b)}} +yj.prototype.w=function(){var a=[];if(null!==this.h){var b=this.h;a[0]=b}null!==this.g&&(b=this.g,a[1]=b);null!==this.b&&(b=this.b,a[2]=b);null!==this.c&&(b=this.c,a[3]=b);null!==this.i&&(b=this.i,a[4]=b);null!==this.a&&(b=this.a,a[5]=b);null!==this.j&&(b=this.j,a[6]=b);null!==this.f&&(b=this.f,a[7]=b);return a};function hk(a){a.h=null;a.g=null;a.b=null;a.c=null;a.i=null;a.a=null;a.j=null;a.f=null}yj.prototype.getExtension=function(){return null}; +function nk(a,b){for(;G(b);)switch(b.a){case 1:var c=N(b);a.h=c;break;case 2:c=N(b);a.g=c;break;case 3:c=K(b);a.b=c;break;case 4:c=K(b);a.c=c;break;case 5:c=N(b);a.i=c;break;case 6:c=K(b);a.a=c;break;case 7:c=K(b);a.j=c;break;case 8:c=K(b);a.f=c;break;default:H(b)}}zj.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.slice();a[0]=b}null!==this.f&&(b=this.f,a[1]=b);null!==this.b&&(b=this.b,b=b.slice(),a[2]=b);null!==this.c&&(b=this.c,a[3]=b);return a}; +function gk(a){a.a=null;a.f=null;a.b=null;a.c=null}zj.prototype.getExtension=function(){return null};function mk(a,b){for(;G(b);)switch(b.a){case 1:var c=N(b);a.a=a.a||[];a.a.push(c);break;case 2:c=K(b);a.f=c;break;case 3:c=N(b);a.b=a.b||[];a.b.push(c);break;case 4:c=N(b);a.c=c;break;default:H(b)}} +Aj.prototype.w=function(){var a=[];if(null!==this.m){var b=this.m;a[0]=b}null!==this.l&&(b=this.l,a[1]=b);null!==this.j&&(b=this.j,b=Oc(b,!0),a[2]=b);null!==this.i&&(b=this.i,a[4]=b);null!==this.o&&(b=this.o,a[5]=b);null!==this.b&&(b=this.b,b=b.slice(),a[6]=b);null!==this.f&&(b=this.f,a[7]=b);null!==this.g&&(b=this.g,a[8]=b);if(null!==this.a){b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[9]=b}null!==this.c&&(b=this.c,b=b.w(),a[10]=b);null!==this.h&&(b=this.h,a[11]=b);return a}; +function ak(a){a.m=null;a.l=null;a.j=null;a.i=null;a.o=null;a.b=null;a.f=null;a.g=null;if(a.a)for(var b=0;b<a.a.length;b++){var c=a.a[b];c&&(c.a=null)}a.a=null;(b=a.c)&&ck(b);a.c=null;a.h=null}Aj.prototype.getExtension=function(){return null}; +function kk(a,b){for(;G(b);)switch(b.a){case 1:var c=N(b);a.m=c;break;case 2:c=N(b);a.l=c;break;case 3:c=qd(b);a.j=c;break;case 5:c=N(b);a.i=c;break;case 6:c=K(b);a.o=c;break;case 7:c=N(b);a.b=a.b||[];a.b.push(c);break;case 8:c=N(b);a.f=c;break;case 9:c=K(b);a.g=c;break;case 10:c=new Bj;O(b,c,sk);a.a=a.a||[];a.a.push(c);break;case 11:c=new Cj;O(b,c,tk);a.c=c;break;case 12:c=N(b);a.h=c;break;default:H(b)}} +function uk(a,b){if(a===b)a=!0;else if(null===a||null===b)a=!1;else{var c;if(c=a.m===b.m&&a.l===b.l&&a.j===b.j&&a.i===b.i&&a.o===b.o&&Cd(a.b,b.b)&&a.f===b.f&&a.g===b.g&&Dd(a.a,b.a,vk)){var d=a.c;c=b.c;if(d===c)c=!0;else if(null===d||null===c)c=!1;else{var e;if(e=d.b===c.b)d=d.a,c=c.a,e=d===c?!0:null===d||null===c?!1:d.b!==c.b||d.a!==c.a?!1:!0;c=e?!0:!1}}a=c&&a.h===b.h?!0:!1}return a}Bj.prototype.w=function(){var a=[];null!==this.a&&(a[0]=this.a);return a};Bj.prototype.getExtension=function(){return null}; +function bk(a){if(null===a)a=null;else{var b=new Bj;b.a=null;b.a=a.a;a=b}return a}function sk(a,b){for(;G(b);)switch(b.a){case 1:a.a=N(b);break;default:H(b)}}function vk(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a?!1:!0}Cj.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}null!==this.a&&(b=this.a,b=b.w(),a[2]=b);return a};function ck(a){a.b=null;var b=a.a;b&&(b.b=null,b.a=null);a.a=null}Cj.prototype.getExtension=function(){return null}; +function tk(a,b){for(;G(b);)switch(b.a){case 1:var c=N(b);a.b=c;break;case 3:c=new Dj;O(b,c,wk);a.a=c;break;default:H(b)}}Dj.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}null!==this.a&&(b=this.a,a[1]=b);return a};function dk(a){var b=new Dj;b.b=null;b.a=null;b.b=a.b;b.a=a.a;return b}Dj.prototype.getExtension=function(){return null};function wk(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.b=c;break;case 2:c=J(b);a.a=c;break;default:H(b)}} +Ej.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}null!==this.c&&(b=this.c,a[1]=b);null!==this.j&&(b=this.j,a[2]=b);null!==this.h&&(b=this.h,a[3]=b);null!==this.a&&(b=this.a,b=b.w(),a[4]=b);null!==this.g&&(b=this.g,a[5]=b);null!==this.i&&(b=this.i,a[6]=b);null!==this.f&&(b=this.f,a[7]=b);null!==this.l&&(b=this.l,a[19]=b);return a};function ek(a){a.b=null;a.c=null;a.j=null;a.h=null;var b=a.a;b&&qk(b);a.a=null;a.g=null;a.i=null;a.f=null;a.l=null}Ej.prototype.getExtension=function(){return null}; +function lk(a,b){for(;G(b);)switch(b.a){case 1:var c=K(b);a.b=c;break;case 2:c=K(b);a.c=c;break;case 3:c=K(b);a.j=c;break;case 4:c=K(b);a.h=c;break;case 5:c=new xj;O(b,c,rk);a.a=c;break;case 6:c=K(b);a.g=c;break;case 7:c=K(b);a.i=c;break;case 8:c=K(b);a.f=c;break;case 20:c=N(b);a.l=c;break;default:H(b)}} +function xk(a,b){if(a===b)a=!0;else if(null===a||null===b)a=!1;else{var c;if(c=a.b===b.b&&a.c===b.c&&a.j===b.j&&a.h===b.h){c=a.a;var d=b.a;c=c===d?!0:null===c||null===d?!1:c.g!==d.g||c.c!==d.c||c.f!==d.f||c.a!==d.a||c.i!==d.i||c.j!==d.j||c.b!==d.b||c.h!==d.h?!1:!0}a=c&&a.g===b.g&&a.i===b.i&&a.f===b.f&&a.l===b.l?!0:!1}return a}Fj.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.w();a[0]=b}return a};function Kj(a){var b=a.a;b&&Lj(b);a.a=null}Fj.prototype.getExtension=function(){return null}; +function Oj(a,b){for(;G(b);)switch(b.a){case 1:var c=new Gj;O(b,c,yk);a.a=c;break;default:H(b)}}Gj.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.w();a[0]=b}null!==this.b&&(b=this.b,a[1]=b);return a};function Lj(a){var b=a.a;b&&Jj(b);a.a=null;a.b=null}Gj.prototype.getExtension=function(){return null};function yk(a,b){for(;G(b);)switch(b.a){case 1:var c=new pj;O(b,c,Nj);a.a=c;break;case 2:c=K(b);a.b=c;break;default:H(b)}} +Hj.prototype.w=function(){var a=[];if(null!==this.c){var b=this.c;a[0]=b}null!==this.h&&(b=this.h,a[1]=b);null!==this.f&&(b=this.f,a[2]=b);null!==this.b&&(b=this.b,b=b.slice(),a[3]=b);null!==this.a&&(b=this.a,b=b.slice(),a[4]=b);null!==this.g&&(b=this.g,a[5]=b);return a};function zk(a){a.c=null;a.h=null;a.f=null;a.b=null;a.a=null;a.g=null}Hj.prototype.getExtension=function(){return null}; +function Ak(a,b){for(;G(b);)switch(b.a){case 1:var c=N(b);a.c=c;break;case 2:c=K(b);a.h=c;break;case 3:c=K(b);a.f=c;break;case 4:c=J(b);a.b=a.b||[];a.b.push(c);break;case 5:c=J(b);a.a=a.a||[];a.a.push(c);break;case 6:c=K(b);a.g=c;break;default:H(b)}};function Bk(){this.b=this.a=null}Bk.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.w();a[0]=b}null!==this.b&&(b=this.b,b=b.w(),a[1]=b);return a};function Ck(a){var b=a.a;b&&Cf(b);a.a=null;(b=a.b)&&Cf(b);a.b=null}Bk.prototype.getExtension=function(){return null};function Dk(a){if(null===a)a=null;else{var b=new Bk;Ck(b);b.a=a.a?Bf(a.a):null;b.b=a.b?Bf(a.b):null;a=b}return a} +function Ek(a,b){for(;G(b);)switch(b.a){case 1:var c=new wf;O(b,c,Df);a.a=c;break;case 2:c=new wf;O(b,c,Df);a.b=c;break;default:H(b)}}function Fk(a,b){return a===b?!0:null===a||null===b?!1:Ef(a.a,b.a)&&Ef(a.b,b.b)?!0:!1};function Gk(){this.a=this.c=this.b=null}Gk.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}null!==this.c&&(b=this.c,a[1]=b);null!==this.a&&(b=this.a,a[2]=b);return a};Gk.prototype.getExtension=function(){return null};function Hk(a,b){for(;G(b);)switch(b.a){case 1:var c=K(b);a.b=c;break;case 2:c=L(b);a.c=c;break;case 3:c=L(b);a.a=c;break;default:H(b)}};function Ik(){this.C=this.s=this.m=this.i=this.f=this.G=this.b=this.I=this.h=this.l=this.J=this.g=this.j=this.v=this.a=this.B=this.A=this.o=this.c=this.u=this.H=this.D=null} +Ik.prototype.w=function(){var a=[];if(null!==this.D){var b=this.D;a[0]=b}null!==this.H&&(b=this.H,a[1]=b);null!==this.u&&(b=this.u,a[2]=b);null!==this.c&&(b=this.c,b=b.w(),a[3]=b);null!==this.o&&(b=this.o,a[4]=b);null!==this.A&&(b=this.A,a[5]=b);null!==this.B&&(b=this.B,a[6]=b);if(null!==this.a){b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[7]=b}null!==this.v&&(b=this.v,a[8]=b);null!==this.j&&(b=this.j,a[9]=b);null!==this.g&&(b=this.g,b=b.w(),a[10]=b);null!==this.J&&(b=this.J,a[11]= +b);null!==this.l&&(b=this.l,a[12]=b);null!==this.h&&(b=this.h,b=b.w(),a[13]=b);null!==this.I&&(b=this.I,a[14]=b);if(null!==this.b){b=this.b;b=b.slice();for(c=0;c<b.length;c++)b[c]=b[c].w();a[15]=b}null!==this.G&&(b=this.G,a[16]=b);null!==this.f&&(b=this.f,b=b.slice(),a[17]=b);null!==this.i&&(b=this.i,b=b.w(),a[18]=b);null!==this.m&&(b=this.m,a[19]=b);null!==this.s&&(b=this.s,a[20]=b);null!==this.C&&(b=this.C,a[21]=b);return a}; +function Jk(a,b){Kk(a);a.D=b.D;a.H=b.H;a.u=b.u;a.c=b.c?Wh(b.c):null;a.o=b.o;a.A=b.A;a.B=b.B;a.a=Bd(b.a,ri);a.v=b.v;a.j=b.j;if(b.g){var c=new Vf;wg(c,b.g)}else c=null;a.g=c;a.J=b.J;a.l=b.l;if(b.h){c=new Gk;var d=b.h;c.b=null;c.c=null;c.a=null;c.b=d.b;c.c=d.c;c.a=d.a}else c=null;a.h=c;a.I=b.I;a.b=Bd(b.b,Dk);a.G=b.G;a.f=Ad(b.f);b.i?(c=new Qf,d=b.i,c.a=null,c.a=d.a):c=null;a.i=c;a.m=b.m;a.s=b.s;a.C=b.C} +function Kk(a){a.D=null;a.H=null;a.u=null;var b=a.c;b&&Xh(b);a.c=null;a.o=null;a.A=null;a.B=null;if(a.a)for(b=0;b<a.a.length;b++){var c=a.a[b];c&&pi(c)}a.a=null;a.v=null;a.j=null;(b=a.g)&&xg(b);a.g=null;a.J=null;a.l=null;if(b=a.h)b.b=null,b.c=null,b.a=null;a.h=null;a.I=null;if(a.b)for(b=0;b<a.b.length;b++)(c=a.b[b])&&Ck(c);a.b=null;a.G=null;a.f=null;if(b=a.i)b.a=null;a.i=null;a.m=null;a.s=null;a.C=null}Ik.prototype.getExtension=function(){return null}; +function Lk(a,b){for(;G(b);)switch(b.a){case 1:var c=L(b);a.D=c;break;case 2:c=L(b);a.H=c;break;case 3:c=K(b);a.u=c;break;case 4:c=new Vh;O(b,c,Yh);a.c=c;break;case 5:c=L(b);a.o=c;break;case 6:c=L(b);a.A=c;break;case 7:c=N(b);a.B=c;break;case 8:c=new oi;O(b,c,si);a.a=a.a||[];a.a.push(c);break;case 9:c=L(b);a.v=c;break;case 10:c=L(b);a.j=c;break;case 11:c=new Vf;O(b,c,Vg);a.g=c;break;case 12:c=N(b);a.J=c;break;case 13:c=N(b);a.l=c;break;case 14:c=new Gk;O(b,c,Hk);a.h=c;break;case 15:c=J(b);a.I=c;break; +case 16:c=new Bk;O(b,c,Ek);a.b=a.b||[];a.b.push(c);break;case 17:c=L(b);a.G=c;break;case 18:c=N(b);a.f=a.f||[];a.f.push(c);break;case 19:c=new Qf;O(b,c,Rf);a.i=c;break;case 20:c=K(b);a.m=c;break;case 21:c=K(b);a.s=c;break;case 22:c=K(b);a.C=c;break;default:H(b)}};function Mk(){this.h=this.i=this.f=this.b=this.g=this.s=this.o=this.m=this.l=this.c=this.a=this.j=null} +Mk.prototype.w=function(){var a=[];if(null!==this.j){var b=this.j;a[0]=b}null!==this.a&&(b=this.a,a[1]=b);null!==this.c&&(b=this.c,a[2]=b);null!==this.l&&(b=this.l,a[3]=b);null!==this.m&&(b=this.m,a[4]=b);null!==this.o&&(b=this.o,a[5]=b);null!==this.s&&(b=this.s,a[6]=b);null!==this.g&&(b=this.g,a[7]=b);null!==this.b&&(b=this.b,a[9]=b);null!==this.f&&(b=this.f,a[10]=b);null!==this.i&&(b=this.i,a[11]=b);null!==this.h&&(b=this.h,a[12]=b);return a}; +function Nk(a){a.j=null;a.a=null;a.c=null;a.l=null;a.m=null;a.o=null;a.s=null;a.g=null;a.b=null;a.f=null;a.i=null;a.h=null}Mk.prototype.getExtension=function(){return null}; +function Ok(a,b){for(;G(b);)switch(b.a){case 1:var c=L(b);a.j=c;break;case 2:c=L(b);a.a=c;break;case 3:c=L(b);a.c=c;break;case 4:c=L(b);a.l=c;break;case 5:c=L(b);a.m=c;break;case 6:c=L(b);a.o=c;break;case 7:c=L(b);a.s=c;break;case 8:c=L(b);a.g=c;break;case 10:c=L(b);a.b=c;break;case 11:c=L(b);a.f=c;break;case 12:c=L(b);a.i=c;break;case 13:c=L(b);a.h=c;break;default:H(b)}};function Pk(){this.a=null}Pk.prototype.w=function(){var a=[];null!==this.a&&(a[0]=this.a);return a};function Qk(a){a.a=null}Pk.prototype.getExtension=function(){return null};function Rk(a,b){for(;G(b);)switch(b.a){case 1:a.a=N(b);break;default:H(b)}};function Sk(){this.P=this.O=this.M=this.h=this.L=this.D=this.g=this.I=this.o=this.s=this.C=this.H=this.B=this.f=this.m=this.A=this.J=this.a=this.G=this.u=this.b=this.i=this.v=this.l=this.K=this.j=this.c=null}function Tk(){this.a=null} +Sk.prototype.w=function(){var a=[];if(null!==this.c){var b=this.c;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[0]=b}null!==this.j&&(b=this.j,b=b.w(),a[2]=b);null!==this.K&&(b=this.K,a[3]=b);null!==this.l&&(b=this.l,b=b.w(),a[5]=b);null!==this.v&&(b=this.v,a[6]=b);null!==this.i&&(b=this.i,b=b.w(),a[7]=b);if(null!==this.b){b=this.b;b=b.slice();for(c=0;c<b.length;c++)b[c]=b[c].w();a[8]=b}null!==this.u&&(b=this.u,a[11]=b);null!==this.G&&(b=this.G,a[12]=b);null!==this.a&&(b=this.a,b=b.w(),a[14]= +b);null!==this.J&&(b=this.J,a[15]=b);null!==this.A&&(b=this.A,a[16]=b);null!==this.m&&(b=this.m,b=b.w(),a[18]=b);null!==this.f&&(b=this.f,b=b.w(),a[19]=b);null!==this.B&&(b=this.B,a[20]=b);null!==this.H&&(b=this.H,a[21]=b);null!==this.C&&(b=this.C,a[22]=b);null!==this.s&&(b=this.s,a[24]=b);null!==this.o&&(b=this.o,b=b.w(),a[25]=b);null!==this.I&&(b=this.I,a[26]=b);null!==this.g&&(b=this.g,b=b.w(),a[27]=b);null!==this.D&&(b=this.D,a[28]=b);null!==this.L&&(b=this.L,a[29]=b);Uk(this);null!==this.h&& +(b=this.h,b=Dc(b),a[30]=b);return a}; +function Vk(a){var b=new Sk;Wk(b);b.c=Bd(a.c,Mj);b.j=a.j?Ti(a.j):null;b.K=a.K;if(a.l){var c=new vj;Yj(c,a.l)}else c=null;b.l=c;b.v=a.v;if(a.i){c=new Hj;var d=a.i;zk(c);c.c=d.c;c.h=d.h;c.f=d.f;c.b=Ad(d.b);c.a=Ad(d.a);c.g=d.g}else c=null;b.i=c;b.b=Bd(a.b,Rj);b.u=a.u;b.G=a.G;a.a?(c=new Ik,Jk(c,a.a)):c=null;b.a=c;b.J=a.J;b.A=a.A;a.m?(c=a.m,d=new Tk,d.a=null,d.a=c.a,c=d):c=null;b.m=c;a.f?(c=new fj,d=a.f,gj(c),c.a=Bd(d.a,Hi),c.b=d.b):c=null;b.f=c;b.B=a.B;b.H=a.H;b.C=a.C;b.s=a.s;a.o?(c=new Pk,d=a.o,Qk(c), +c.a=d.a):c=null;b.o=c;b.I=a.I;a.g?(c=new Mk,d=a.g,Nk(c),c.j=d.j,c.a=d.a,c.c=d.c,c.l=d.l,c.m=d.m,c.o=d.o,c.s=d.s,c.g=d.g,c.b=d.b,c.f=d.f,c.i=d.i,c.h=d.h):c=null;b.g=c;b.D=a.D;b.L=a.L;b.h=a.h?new Uint8Array(a.h):null;b.M=a.M;b.O=a.O;b.P=a.P;return b} +function Wk(a){if(a.c)for(var b=0;b<a.c.length;b++){var c=a.c[b];c&&Jj(c)}a.c=null;(b=a.j)&&Ui(b);a.j=null;a.K=null;(b=a.l)&&Zj(b);a.l=null;a.v=null;(b=a.i)&&zk(b);a.i=null;if(a.b)for(b=0;b<a.b.length;b++)(c=a.b[b])&&Qj(c);a.b=null;a.u=null;a.G=null;(b=a.a)&&Kk(b);a.a=null;a.J=null;a.A=null;if(b=a.m)b.a=null;a.m=null;(b=a.f)&&gj(b);a.f=null;a.B=null;a.H=null;a.C=null;a.s=null;(b=a.o)&&Qk(b);a.o=null;a.I=null;(b=a.g)&&Nk(b);a.g=null;a.D=null;a.L=null;a.h=null;a.M=null;a.O=null} +Sk.prototype.getExtension=function(){return null}; +function Xk(a,b){for(a.P=jd(b);G(b);)switch(b.a){case 1:var c=new pj;O(b,c,Nj);a.c=a.c||[];a.c.push(c);break;case 3:c=new Pi;O(b,c,Vi);a.j=c;break;case 4:c=J(b);a.K=c;break;case 6:c=new vj;O(b,c,jk);a.l=c;break;case 7:c=N(b);a.v=c;break;case 8:c=new Hj;O(b,c,Ak);a.i=c;break;case 9:c=new sj;O(b,c,Sj);a.b=a.b||[];a.b.push(c);break;case 12:c=K(b);a.u=c;break;case 13:c=L(b);a.G=c;break;case 15:c=new Ik;O(b,c,Lk);a.a=c;break;case 16:c=K(b);a.J=c;break;case 17:c=K(b);a.A=c;break;case 19:c=new Tk;O(b,c, +Yk);a.m=c;break;case 20:c=new fj;O(b,c,hj);a.f=c;break;case 21:c=L(b);a.B=c;break;case 22:c=K(b);a.H=c;break;case 23:c=J(b);a.C=c;break;case 25:c=K(b);a.s=c;break;case 26:c=new Pk;O(b,c,Rk);a.o=c;break;case 27:c=K(b);a.I=c;break;case 28:c=new Mk;O(b,c,Ok);a.g=c;break;case 29:c=N(b);a.D=c;break;case 30:c=N(b);a.L=c;break;case 31:null===a.M&&(a.M=b.b);kd(b);a.O=id(b);break;default:H(b)}} +function Zk(a,b){if(a===b)a=!0;else if(null===a||null===b)a=!1;else{var c;if(c=Dd(a.c,b.c,Pj)&&Zi(a.j,b.j)&&a.K===b.K){c=a.l;var d=b.l;if(c===d)c=!0;else if(null===c||null===d)c=!1;else{var e;if(e=uk(c.j,d.j)&&xk(c.b,d.b)&&c.m===d.m&&c.o===d.o){e=c.c;var f=d.c;e=e===f?!0:null===e||null===f?!1:e.o!==f.o||e.A!==f.A||e.T!==f.T||e.a!==f.a||e.b!==f.b||e.I!==f.I||e.G!==f.G||e.H!==f.H||e.i!==f.i||e.D!==f.D||e.C!==f.C||e.B!==f.B||e.O!==f.O||e.M!==f.M||e.h!==f.h||e.m!==f.m||e.S!==f.S||e.P!==f.P||e.j!==f.j|| +e.l!==f.l||e.V!==f.V||e.J!==f.J||e.s!==f.s||e.U!==f.U||e.W!==f.W||e.L!==f.L||e.K!==f.K||e.c!==f.c||e.v!==f.v||e.g!==f.g||e.f!==f.f||e.u!==f.u?!1:!0}if(e=e&&c.s===d.s&&c.K===d.K&&c.v===d.v&&c.U===d.U)e=c.h,f=d.h,e=e===f?!0:null===e||null===f?!1:e.b!==f.b||e.a!==f.a?!1:!0;if(e=e&&c.O===d.O&&c.M===d.M&&c.G===d.G&&Cd(c.g,d.g)&&c.H===d.H)e=c.f,f=d.f,e=e===f?!0:null===e||null===f?!1:Cd(e.a,f.a)&&e.f===f.f&&Cd(e.b,f.b)&&e.c===f.c?!0:!1;e&&(e=c.i,f=d.i,e=e===f?!0:null===e||null===f?!1:e.a!==f.a||e.c!==f.c|| +e.b!==f.b?!1:!0);e&&(e=c.l,f=d.l,e=e===f?!0:null===e||null===f?!1:e.h!==f.h||e.g!==f.g||e.b!==f.b||e.c!==f.c||e.i!==f.i||e.a!==f.a||e.j!==f.j||e.f!==f.f?!1:!0);c=e&&c.B===d.B&&c.C===d.C&&c.A===d.A&&c.V===d.V&&c.L===d.L&&c.I===d.I&&c.D===d.D&&Dd(c.a,d.a,pk)&&c.P===d.P&&c.T===d.T&&c.J===d.J&&c.u===d.u&&c.S===d.S?!0:!1}}if(c=c&&a.v===b.v)c=a.i,d=b.i,c=c===d?!0:null===c||null===d?!1:c.c===d.c&&c.h===d.h&&c.f===d.f&&Cd(c.b,d.b)&&Cd(c.a,d.a)&&c.g===d.g?!0:!1;if(c=c&&Dd(a.b,b.b,Tj)&&a.u===b.u&&a.G===b.G)if(c= +a.a,d=b.a,c===d)c=!0;else if(null===c||null===d)c=!1;else{if(e=c.D===d.D&&c.H===d.H&&c.u===d.u&&Zh(c.c,d.c)&&c.o===d.o&&c.A===d.A&&c.B===d.B&&Dd(c.a,d.a,ti)&&c.v===d.v&&c.j===d.j)if(e=c.g,f=d.g,e===f)e=!0;else if(null===e||null===f)e=!1;else{var g;if(g=e.rb===f.rb&&e.K===f.K){g=e.v;var h=f.v;g=g===h?!0:null===g||null===h?!1:g.a!==h.a||g.c!==h.c||g.b!==h.b?!1:!0}if(g=g&&e.Ca===f.Ca&&ah(e.i,f.i)&&Dd(e.a,f.a,ah)&&e.qb===f.qb&&e.Ra===f.Ra&&e.Pa===f.Pa&&e.V===f.V&&e.fa===f.fa&&e.U===f.U&&e.M===f.M&&e.ha=== +f.ha&&e.W===f.W&&e.Y===f.Y&&e.O===f.O&&e.Da===f.Da&&e.ja===f.ja&&e.pa===f.pa&&e.ia===f.ia&&e.ga===f.ga&&e.Oa===f.Oa&&e.T===f.T&&e.L===f.L&&e.S===f.S)g=e.u,h=f.u,g=g===h?!0:null===g||null===h?!1:g.f!==h.f||g.h!==h.h||g.a!==h.a||g.b!==h.b||g.g!==h.g||g.c!==h.c?!1:!0;g&&(g=e.j,h=f.j,g=g===h?!0:null===g||null===h?!1:g.c!==h.c||g.a!==h.a||g.b!==h.b?!1:!0);if(g=g&&e.Ga===f.Ga&&e.Sa===f.Sa&&Cd(e.m,f.m)&&e.Ja===f.Ja&&e.La===f.La&&e.B===f.B&&e.Ka===f.Ka&&e.jb===f.jb&&e.ya===f.ya&&e.sb===f.sb&&e.s===f.s&&Dd(e.c, +f.c,ah)&&e.Ia===f.Ia&&e.Qa===f.Qa&&e.Ba===f.Ba&&e.J===f.J&&e.I===f.I&&e.H===f.H&&e.G===f.G&&e.Z===f.Z&&e.Bb===f.Bb&&e.Wa===f.Wa&&e.Za===f.Za&&e.Lb===f.Lb&&e.C===f.C&&e.P===f.P&&mh(e.o,f.o)&&e.Kb===f.Kb&&Dd(e.f,f.f,oh)&&e.Jb===f.Jb)g=e.l,h=f.l,g=g===h?!0:null===g||null===h?!1:g.b!==h.b||g.a!==h.a?!1:!0;if(g=g&&Dd(e.b,f.b,nh)&&e.D===f.D&&e.ra===f.ra&&e.va===f.va)g=e.A,h=f.A,g=g===h?!0:null===g||null===h?!1:g.a!==h.a||g.b!==h.b?!1:!0;if(g=g&&e.ib===f.ib&&e.$a===f.$a)g=e.h,h=f.h,g=g===h?!0:null===g|| +null===h?!1:g.c!==h.c||g.f!==h.f||g.g!==h.g||g.b!==h.b||g.a!==h.a?!1:!0;e=g&&Dd(e.g,f.g,dh)?!0:!1}if(e=e&&c.J===d.J&&c.l===d.l)e=c.h,f=d.h,e=e===f?!0:null===e||null===f?!1:e.b!==f.b||e.c!==f.c||e.a!==f.a?!1:!0;if(e=e&&c.I===d.I&&Dd(c.b,d.b,Fk)&&c.G===d.G&&Cd(c.f,d.f))e=c.i,f=d.i,e=e===f?!0:null===e||null===f?!1:e.a!==f.a?!1:!0;c=e&&c.m===d.m&&c.s===d.s&&c.C===d.C?!0:!1}if(c=c&&a.J===b.J&&a.A===b.A)c=a.m,d=b.m,c=c===d?!0:null===c||null===d?!1:c.a!==d.a?!1:!0;c&&(c=a.f,d=b.f,c=c===d?!0:null===c||null=== +d?!1:Dd(c.a,d.a,Ji)&&c.b===d.b?!0:!1);if(c=c&&a.B===b.B&&a.H===b.H&&a.C===b.C&&a.s===b.s)c=a.o,d=b.o,c=c===d?!0:null===c||null===d?!1:c.a!==d.a?!1:!0;if(c=c&&a.I===b.I)c=a.g,d=b.g,c=c===d?!0:null===c||null===d?!1:c.j!==d.j||c.a!==d.a||c.c!==d.c||c.l!==d.l||c.m!==d.m||c.o!==d.o||c.s!==d.s||c.g!==d.g||c.b!==d.b||c.f!==d.f||c.i!==d.i||c.h!==d.h?!1:!0;c&&a.D===b.D&&a.L===b.L?(Uk(a),a=Cd(a.h,b.h)?!0:!1):a=!1}return a}Sk.prototype.xd=function(){return null!=this.a?!0:!1}; +Sk.prototype.vd=function(){null===this.a&&(this.a=new Ik);return this.a};function Uk(a){null!=a.M&&null==a.h&&(a.h=Gd(a.P,a.M,a.O))}Tk.prototype.w=function(){var a=[];null!==this.a&&(a[0]=this.a);return a};Tk.prototype.getExtension=function(){return null};function Yk(a,b){for(;G(b);)switch(b.a){case 1:a.a=N(b);break;default:H(b)}};function $k(a){this.data=a||[]}var al;F($k,W);var bl,cl,dl;function el(){bl={a:-1,F:[]};bl.F=[,me(),he(1),Q,U,Vd("u",4278190080),V(new Pe([]),Re()),R,V(new Me([]),Oe()),P,P,he(1)]}function fl(){var a=cl={a:-1,F:[]},b=new of([]);if(!pf){var c=[];pf={a:-1,F:c};c[1]=pe(oe());c[500]=V(new ef([]),gf());c[15]=V(new Me([]),Oe())}a.F=[,V(b,pf),Q,Zd(1),R]}function gl(){dl={a:-1,F:[]};dl.F=[,V(new ne([]),oe()),$d,Q,Zd(1),Q]};function hl(a){this.data=a||[]}var il;F(hl,W);function jl(a){this.data=a||[]}var kl;F(jl,W);function ll(a){this.data=a||[]}var ml;F(ll,W);var nl;function ol(){il||(il={a:-1,F:[,,,Yd,Yd]});return il}function pl(){ml||(ml={a:-1,F:[,P,P]});return ml}function ql(){nl={a:-1,F:[]};nl.F=[,V(new ll([]),pl()),V(new ll([]),pl())]};function rl(a){this.data=a||[]}var sl;F(rl,W);function tl(a){this.data=a||[]}var ul;F(tl,W);function vl(){if(!ul){var a=ul={a:-1,F:[]},b=new rl([]);sl||(sl={a:-1,F:[,P,P,P,T,U]});a.F=[,V(b,sl),V(new hl([]),ol()),U,U,,,R,P,R,U,T,he(1)]}return ul};function wl(a){this.data=a||[]}var xl;F(wl,W);function yl(a){this.data=a||[]}var zl;F(yl,W);function Al(a){this.data=a||[]}var Bl;F(Al,W);var Cl;function Dl(a){this.data=a||[]}var El;F(Dl,W);function Fl(a){this.data=a||[]}var Gl;F(Fl,W);function Hl(a){this.data=a||[]}var Il;F(Hl,W);function Jl(a){this.data=a||[]}var Kl;F(Jl,W);function Ll(){if(!El){var a=El={a:-1,F:[]},b=new Fl([]);Gl||(Gl={a:-1,F:[,Yd,Yd,Yd]});b=V(b,Gl);var c=new Hl([]);Il||(Il={a:-1,F:[,$d,$d,$d]});c=V(c,Il);var d=new Jl([]);Kl||(Kl={a:-1,F:[,P,P]});a.F=[,b,c,V(d,Kl),$d]}return El}Fl.prototype.ud=function(){return X(this,0)};function Ml(a){this.data=a||[]}var Nl;F(Ml,W);function Ol(){Nl||(Nl={a:-1,F:[]},Nl.F=[,U,U,V(new Dl([]),Ll()),V(new hl([]),ol()),T,R,R,,T,ae(2147483647),U,le]);return Nl};function Pl(a){this.data=a||[]}var Ql;F(Pl,W);function Rl(a){this.data=a||[]}var Sl;F(Rl,W);function Tl(a){this.data=a||[]}var Ul;F(Tl,W);function Vl(a){this.data=a||[]}var Wl;F(Vl,W);function Xl(a){this.data=a||[]}var Yl;F(Xl,W);function Zl(a){this.data=a||[]}var $l;F(Zl,W);function am(a){this.data=a||[]}var bm;F(am,W);var cm;function dm(a){this.data=a||[]}var em;F(dm,W);function fm(a){this.data=a||[]}var gm;F(fm,W); +function hm(){var a=bm={a:-1,F:[]},b=new dm([]);em||(em={a:-1,F:[,U,U,U,$d,$d]});b=V(b,em);if(!cm){var c=cm={a:-1,F:[]},d=V(new Pe([]),Re()),e=new Xl([]);Yl||(Yl={a:-1,F:[,,,Yd,Yd]});c.F=[,d,,U,,V(e,Yl)]}c=pe(cm);d=new Vl([]);if(!Wl){e=Wl={a:-1,F:[]};var f=new Tl([]);Ul||(Ul={a:-1,F:[]},Ul.F=[,T,Vd("v","0")]);f=V(f,Ul);var g=new Rl([]);if(!Sl){var h=Sl={a:-1,F:[]},k=ae(1),l=new Pl([]);Ql||(Ql={a:-1,F:[,P,P]});h.F=[,U,k,T,T,R,U,U,$d,V(l,Ql),P,T]}e.F=[,ie,f,,ie,,,U,T,V(g,Sl),,,ke,P,P,P,R,,R,R,ie,T]}d= +V(d,Wl);e=new tf([]);uf||(uf={a:-1,F:[]},uf.F=[,me(),me()]);e=V(e,uf);f=new jl([]);kl||(kl={a:-1,F:[]},kl.F=[,,,V(new hl([]),ol()),V(new hl([]),ol())]);f=V(f,kl);g=V(new Ml([]),Ol());h=new fm([]);gm||(gm={a:-1,F:[,R,U,ke]});h=V(h,gm);k=he(1);l=new Zl([]);$l||($l={a:-1,F:[,T,U]});a.F=[,U,b,c,d,U,e,,f,,R,R,U,g,,,,,U,h,k,V(l,$l)]};var im;function jm(a){this.data=a||[]}var km;F(jm,W);function lm(a){this.data=a||[]}var mm;F(lm,W);function nm(a){this.data=a||[]}var om;F(nm,W);function pm(a){this.data=a||[]}var qm;F(pm,W);function rm(a){this.data=a||[]}var sm;F(rm,W);function tm(a){this.data=a||[]}var um;F(tm,W);function vm(){um={a:-1,F:[]};um.F=[,R,P,P,R,,,P,,U,,,,,,,,R,R,,ae(-1),,,R,P,R,P,P,Vd("d",1),R,,,P,P,,,,,,P,P,P,R,ae(10),R,R,P,P,R,R,R,R,U]};function wm(a){this.data=a||[]}var xm;F(wm,W);function ym(a){this.data=a||[]}var zm;F(ym,W);var Am;function Bm(a){this.data=a||[]}var Cm;F(Bm,W);function Dm(a){this.data=a||[]}var Em;F(Dm,W);function Fm(a){this.data=a||[]}var Gm;F(Fm,W);var Hm;function Im(a){this.data=a||[]}var Jm;F(Im,W);function Km(a){this.data=a||[]}var Lm;F(Km,W);function Mm(a){this.data=a||[]}var Nm;F(Mm,W);function Om(a){this.data=a||[]}var Pm;F(Om,W);var Qm;function Rm(a){this.data=a||[]}var Sm;F(Rm,W);function Tm(a){this.data=a||[]}var Um;F(Tm,W); +function Vm(a){this.data=a||[]}var Wm;F(Vm,W);function Xm(a){this.data=a||[]}var Ym;F(Xm,W);function Zm(a){this.data=a||[]}var $m;F(Zm,W);function an(a){this.data=a||[]}var bn;F(an,W);function cn(){if(!zm){var a=zm={a:-1,F:[]},b=V(new hl([]),ol()),c=he(4),d=new wm([]);xm||(xm={a:-1,F:[,U,$d,U,U]});d=V(d,xm);var e=new Xm([]);if(!Ym){var f=Ym={a:-1,F:[]},g=new Zm([]);$m||($m={a:-1,F:[]},$m.F=[,V(new ym([]),cn()),R]);f.F=[,V(g,$m)]}a.F=[,U,U,b,U,c,T,d,U,R,,R,U,U,U,,V(e,Ym),P]}return zm} +function dn(){Cm={a:-1,F:[,T,R]}}function en(){Em={a:-1,F:[]};Em.F=[,T,he(1),Vd("j","")]}function fn(){Hm={a:-1,F:[,P]}}function gn(){Lm={a:-1,F:[]};Lm.F=[,he(6),he(1),ge(!0),R,T,R,R,R]}function hn(){Nm={a:-1,F:[]};Nm.F=[,ie,ge(!0),ie,T]}function jn(){var a=Pm={a:-1,F:[]},b=he(1E3),c=he(1),d=Vd("j",""),e=he(1);Qm||(Qm={a:-1,F:[,T]});var f=pe(Qm),g=new Rm([]);if(!Sm){var h=Sm={a:-1,F:[]},k=he(1),l=new Tm([]);Um||(Um={a:-1,F:[,P,P]});h.F=[,k,,V(l,Um)]}a.F=[,b,c,d,,e,R,ie,T,R,f,V(g,Sm),T]} +function kn(){var a=Wm={a:-1,F:[]},b=ge(!0),c=ge(!0),d=new Im([]);Jm||(Jm={a:-1,F:[,,R,R,R,R,T,T,,R,T]});a.F=[,R,R,b,c,V(d,Jm),ge(!0),R,R,,,,,,,,,,,,he(1)]};var ln;function mn(){ln={a:-1,F:[]};ln.F=[,V(new Kf([]),Nf()),V(new Kf([]),Nf())]};function nn(a){this.data=a||[]}var on;F(nn,W);function pn(){on={a:-1,F:[,R,U,U]}};function qn(a){this.data=a||[]}var rn;F(qn,W);function sn(a){this.data=a||[]}var tn;F(sn,W);function un(a){this.data=a||[]}var vn;F(un,W);function wn(a){this.data=a||[]}var xn;F(wn,W);function yn(a){this.data=a||[]}var zn;F(yn,W); +function An(){var a=xn={a:-1,F:[]},b=pe(cn()),c=V(new Dl([]),Ll()),d=new Fm([]);if(!Gm){var e=Gm={a:-1,F:[]},f=new Om([]);Pm||jn();f=V(f,Pm);var g=new Vm([]);Wm||kn();g=V(g,Wm);var h=ge(!0),k=ge(!0),l=new tm([]);um||vm();l=V(l,um);var m=he(2),n=new Bm([]);Cm||dn();n=V(n,Cm);var p=ge(!0),q=ge(!0),t=new Mm([]);Nm||hn();t=V(t,Nm);var v=new Dm([]);Em||en();v=V(v,Em);var u=new Km([]);Lm||gn();u=V(u,Lm);var w=ge(!0),y=ge(!0);Hm||fn();e.F=[,f,g,h,k,,l,R,R,m,R,n,p,q,R,ce,R,t,,v,u,,,,,R,R,,,,,w,,y,R,R,,R, +pe(Hm),R,R,R,R,ae(3)]}d=V(d,Gm);e=he(2);f=new an([]);bn||(bn={a:-1,F:[,T,R,R,ce,ce,R]});f=V(f,bn);Am||(Am={a:-1,F:[]},Am.F=[,P,V(new hl([]),ol()),U,$d,R]);g=pe(Am);h=new qn([]);rn||(k=rn={a:-1,F:[]},l=V(new bi([]),di()),ui||vi(),m=pe(ui),n=new qh([]),rh||Rh(),n=V(n,rh),p=new nn([]),on||pn(),p=V(p,on),ln||mn(),q=pe(ln),t=new Sf([]),Tf||Uf(),k.F=[,U,U,R,l,U,U,T,m,U,U,n,T,T,p,P,q,U,ie,V(t,Tf),R,R,R]);h=V(h,rn);k=new yn([]);zn||(zn={a:-1,F:[]},zn.F=[,he(1)]);k=V(k,zn);l=new rm([]);sm||(m=sm={a:-1,F:[]}, +nl||ql(),m.F=[,pe(nl),R]);l=V(l,sm);m=ge(!0);n=new un([]);vn||(vn={a:-1,F:[,T]});n=V(n,vn);p=new sn([]);tn||(tn={a:-1,F:[,U,U,U,U,U,U,U,U,,U,U,U,U]});a.F=[,b,,c,P,,d,e,f,g,,,R,U,,h,R,R,,k,l,U,R,P,,m,n,R,V(p,tn),T,T,le]}wn.prototype.xd=function(){return xe(this,14)};wn.prototype.vd=function(){return new qn(this.data[14])};function Bn(a){this.data=a||[]}var Cn;F(Bn,W);function Dn(a){this.data=a||[]}var En;F(Dn,W);function Fn(a){this.data=a||[]}var Gn;F(Fn,W);var Hn;function In(a){this.data=a||[]}var Jn;F(In,W);function Kn(a){this.data=a||[]}var Ln;F(Kn,W);var Mn; +function Nn(){if(!Cn){var a=Cn={a:-1,F:[]},b=V(new Bn([]),Nn()),c=V(new Ml([]),Ol()),d=new wl([]);if(!xl){var e=xl={a:-1,F:[]},f=new yl([]);zl||(zl={a:-1,F:[]},zl.F=[,,,,pe(vl())]);f=V(f,zl);var g=new Al([]);Bl||(Bl={a:-1,F:[,ke,P]});g=V(g,Bl);Cl||(Cl={a:-1,F:[]},Cl.F=[,U,V(new hl([]),ol()),T]);e.F=[,,f,g,pe(Cl)]}d=V(d,xl);e=V(new tl([]),vl());f=new wn([]);xn||An();f=V(f,xn);g=he(1);var h=new am([]);bm||hm();h=V(h,bm);var k=new jm([]);if(!km){var l=km={a:-1,F:[]},m=new lm([]);mm||(mm={a:-1,F:[]}, +mm.F=[,,,,,R,R,,R,ge(!0)]);m=V(m,mm);var n=new nm([]);om||(om={a:-1,F:[,R,R]});n=V(n,om);var p=new pm([]);qm||(qm={a:-1,F:[,,,,,,T,T,T]});l.F=[,,U,,,,,,,,,,,,R,,,,m,,,n,V(p,qm)]}k=V(k,km);im||(im={a:-1,F:[]},im.F=[,V(new Pe([]),Re()),U,V(new ne([]),oe())]);l=pe(im);Hn||(Hn={a:-1,F:[,T,U]});m=pe(Hn);n=new Dn([]);if(!En){p=En={a:-1,F:[]};var q=new Fn([]);Gn||(Gn={a:-1,F:[,ke,fe]});p.F=[,T,V(q,Gn)]}n=V(n,En);p=new In([]);Jn||(q=Jn={a:-1,F:[]},Mn||(Mn={a:-1,F:[,,U,ke,R,T]}),q.F=[,pe(Mn),U,U,Vd("j",""), +pe(ol()),P]);p=V(p,Jn);q=V(new hl([]),ol());var t=new Kn([]);Ln||(Ln={a:-1,F:[,U]});a.F=[,b,c,,,d,e,,f,,U,g,h,k,R,,l,U,m,ee,n,ie,p,q,V(t,Ln)]}return Cn}Bn.prototype.getContext=function(){return new Bn(this.data[0])};Dn.prototype.Ea=function(){return ye(this,0,0)};function On(a){this.data=a||[]}var Pn;F(On,W);function Qn(a){this.data=a||[]}var Rn;F(Qn,W);On.prototype.wa=function(){return ze(this,1)};Qn.prototype.na=function(){return ze(this,1)};function Sn(a){this.data=a||[]}var Tn;F(Sn,W);function Un(a){this.data=a||[]}var Vn;F(Un,W);function Wn(){Vn={a:-1,F:[,je,U]}}Un.prototype.na=function(){return ze(this,1)};function Xn(){return B(x.URL)&&B(x.URL.createObjectURL)?x.URL:B(x.webkitURL)&&B(x.webkitURL.createObjectURL)?x.webkitURL:B(x.createObjectURL)?x:null};function Yn(a,b,c){return Math.min(Math.max(a,b),c)}function Zn(a){a%=360;return 0>360*a?a+360:a}function $n(a,b,c){return a+c*(b-a)}function ao(a){return a*Math.PI/180}function bo(a){return Oa(arguments,function(a,c){return a+c},0)}function co(a){return bo.apply(null,arguments)/arguments.length};function eo(a,b){this.x=B(a)?a:0;this.y=B(b)?b:0}eo.prototype.ceil=function(){this.x=Math.ceil(this.x);this.y=Math.ceil(this.y);return this};eo.prototype.floor=function(){this.x=Math.floor(this.x);this.y=Math.floor(this.y);return this};eo.prototype.round=function(){this.x=Math.round(this.x);this.y=Math.round(this.y);return this};function fo(a,b){this.width=a;this.height=b}fo.prototype.ceil=function(){this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};fo.prototype.floor=function(){this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};fo.prototype.round=function(){this.width=Math.round(this.width);this.height=Math.round(this.height);return this};function go(a){return document.createElement(String(a))};function ho(a,b){x.setTimeout(function(){try{a()}catch(c){throw c;}},b)};function io(a){this.a=a||go("CANVAS");this.b=[];this.c=1}io.prototype.addEventListener=function(a,b){this.b.push({type:a,listener:b});this.a.addEventListener(a,b,!1)};io.prototype.removeEventListener=function(a,b){for(var c=0;c<this.b.length;c++)if(b===this.b[c].listener&&a===this.b[c].type){this.b.splice(c,1);break}this.a.removeEventListener(a,b,!1)}; +io.prototype.dispatchEvent=function(a){for(var b=!1,c=0;c<this.b.length;c++)if(a.type==this.b[c].type){var d=this.b[c].listener;b="function"===typeof d?b|d(a):b|d.handleEvent(a)}return b};function jo(a,b){Qb.call(this,"RenderComplete",a);this.startTime=b}F(jo,Qb);function ko(a,b){Qb.call(this,"RenderStart",a);this.startTime=b}F(ko,Qb);function lo(a,b,c){var d=c||x.document;if(d){var e=null;c=null;for(var f=0;f<mo.length;f+=2)if(B(d[mo[f]])){e=mo[f];c=mo[f+1];break}e&&c&&(f=function(){a(!d[e])},b?b.cb(d,c,f):dc(d,c,f))}}var mo="hidden visibilitychange webkitHidden webkitvisibilitychange mozHidden mozvisibilitychange msHidden msvisibilitychange".split(" ");function no(a){Ib.call(this);this.b=a;this.a={}}F(no,Ib);var oo=[];r=no.prototype;r.cb=function(a,b,c,d){return po(this,a,b,c,d)};function po(a,b,c,d,e,f){va(c)||(c&&(oo[0]=c.toString()),c=oo);for(var g=0;g<c.length;g++){var h=dc(b,c[g],d||a.handleEvent,e||!1,f||a.b||a);if(!h)break;a.a[h.key]=h}return a}r.cc=function(a,b,c,d){return qo(this,a,b,c,d)}; +function qo(a,b,c,d,e,f){if(va(c))for(var g=0;g<c.length;g++)qo(a,b,c[g],d,e,f);else{b=ec(b,c,d||a.handleEvent,e,f||a.b||a);if(!b)return a;a.a[b.key]=b}return a}r.Sd=function(a,b,c,d,e){if(va(b))for(var f=0;f<b.length;f++)this.Sd(a,b[f],c,d,e);else c=c||this.handleEvent,d=za(d)?!!d.capture:!!d,e=e||this.b||this,c=fc(c),d=!!d,b=Ub(a)?a.tc(b,c,d,e):a?(a=hc(a))?a.tc(b,c,d,e):null:null,b&&(mc(b),delete this.a[b.key])};function ro(a){gb(a.a,function(a,c){this.a.hasOwnProperty(c)&&mc(a)},a);a.a={}} +r.X=function(){no.R.X.call(this);ro(this)};r.handleEvent=function(){throw Error("EventHandler.handleEvent not implemented");};function so(a,b,c){rc.call(this);this.f=new no(this);Jb(this,this.f);this.b=a;this.g=!!c;this.a=null;this.c=!1;to(this,b)}F(so,rc);function to(a,b){lo(function(b){b&&uo(a)},a.f,b)}function uo(a){a.a&&!a.c&&(a.b.Ue(a),a.c=!0)}function vo(a){a.c=!1;if(!a.O()&&a.a){var b=E();a.dispatchEvent(new ko(a,b));a.a&&a.a.wc();a.dispatchEvent(new jo(a,b,E()));a.g&&uo(a)}};function wo(){this.a=this.f=!1;this.b=void 0;this.h=this.g=this.i=this.c=!1};function xo(a){return(a=a.exec(cb))?a[1]:""}var yo=function(){if(uc)return xo(/Firefox\/([0-9.]+)/);if(pb||qb||ob)return zb;if(yc)return kb()||fb("iPad")||fb("iPod")?xo(/CriOS\/([0-9.]+)/):xo(/Chrome\/([0-9.]+)/);if(zc&&!(kb()||fb("iPad")||fb("iPod")))return xo(/Version\/([0-9.]+)/);if(vc||wc){var a=/Version\/(\S+).*Mobile\/(\S+)/.exec(cb);if(a)return a[1]+"."+a[2]}else if(xc)return(a=xo(/Android\s+([0-9.]+)/))?a:xo(/Version\/([0-9.]+)/);return""}();var zo=["webgl","experimental-webgl","moz-webgl"],Ao=0; +function Bo(a,b,c){var d=b||new wo;if(d.c&&!Co())return Ao=7,null;b=b||new wo;var e={alpha:!0,stencil:!0,preserveDrawingBuffer:!1,failIfMajorPerformanceCaveat:!b.a&&!0};b.f&&(e.antialias=!1);rb&&!Ab(25)&&(e.preserveDrawingBuffer=!0);c=(c||Do)(a,e);if(!c)return Ao=1,null;c.getExtension("WEBGL_debug_renderer_info")?(b=c.getParameter(37446),Eo=Fo(b)):Eo=null;if(d.c&&!c.getExtension("ANGLE_instanced_arrays"))return Ao=7,null;if(c.drawingBufferWidth!=a.width||c.drawingBufferHeight!=a.height)return Ao= +2,null;if(4>c.getParameter(35660))return Ao=3,null;a=c.getParameter(3379);if(B(d.b)&&a<d.b)return Ao=6,null;if(23>c.getShaderPrecisionFormat(35632,36338).precision)return Ao=4,null;a=Eo;return pb&&!a?(Ao=8,null):!d.a&&a&&("Intel Q45"==a&&(pb||uc)||-1!=Go.indexOf(a))?(Ao=5,null):c}function Do(a,b){for(var c=null,d=zo.length,e=0;e<d;++e){try{c=a.getContext(zo[e],b)}catch(f){}if(c)return c}return null}var Eo=void 0;function Co(){return yc&&tb&&!(0<=ab(yo,"30"))||uc&&tb&&!(0<=ab(yo,"27"))?!1:!0} +function Fo(a){if(void 0===a)return null;a=a.toLowerCase();var b=a.match(/angle \((.*)\)/);b&&(a=b[1],a=a.replace(/\s*direct3d.*$/,""));a=a.replace(/\s*\([^\)]*wddm[^\)]*\)/,"");var c=a;0>c.indexOf("intel")?b=null:(b=["Intel"],0<=c.indexOf("mobile")&&b.push("Mobile"),(0<=c.indexOf("gma")||0<=c.indexOf("graphics media accelerator"))&&b.push("GMA"),0<=c.indexOf("haswell")?b.push("Haswell"):0<=c.indexOf("ivy")?b.push("HD 4000"):0<=c.indexOf("sandy")?b.push("HD 3000"):0<=c.indexOf("ironlake")?b.push("HD"): +(0<=c.indexOf("hd")&&b.push("HD"),(c=c.match(Ho))&&b.push(c[1].toUpperCase())),b=b.join(" "));if(b)return b;b=a;if(0>b.indexOf("nvidia")&&0>b.indexOf("quadro")&&0>b.indexOf("geforce")&&0>b.indexOf("nvs"))b=null;else{c=["nVidia"];0<=b.indexOf("geforce")&&c.push("geForce");0<=b.indexOf("quadro")&&c.push("Quadro");0<=b.indexOf("nvs")&&c.push("NVS");b.match(/\bion\b/)&&c.push("ION");b.match(/gtx\b/)?c.push("GTX"):b.match(/gts\b/)?c.push("GTS"):b.match(/gt\b/)?c.push("GT"):b.match(/gs\b/)?c.push("GS"): +b.match(/ge\b/)?c.push("GE"):b.match(/fx\b/)&&c.push("FX");var d=b.match(Ho);d&&c.push(d[1].toUpperCase().replace("GS",""));0<=b.indexOf("titan")?c.push("TITAN"):0<=b.indexOf("ti")&&c.push("Ti");b=c.join(" ")}if(b)return b;c=a;0>c.indexOf("amd")&&0>c.indexOf("ati")&&0>c.indexOf("radeon")&&0>c.indexOf("firegl")&&0>c.indexOf("firepro")?b=null:(b=["AMD"],0<=c.indexOf("mobil")&&b.push("Mobility"),d=c.indexOf("radeon"),0<=d&&b.push("Radeon"),0<=c.indexOf("firepro")?b.push("FirePro"):0<=c.indexOf("firegl")&& +b.push("FireGL"),0<=c.indexOf("hd")&&b.push("HD"),(c=(0<=d?c.substring(d):c).match(Ho))&&b.push(c[1].toUpperCase().replace("HD","")),b=b.join(" "));return b?b:a.substring(0,100)}var Ho=/([a-z0-9]*\d+[a-z0-9]*)/,Go="microsoft basic render driver;vmware svga 3d;Intel 965GM;Intel B43;Intel G41;Intel G45;Intel G965;Intel GMA 3600;Intel Mobile 4;Intel Mobile 45;Intel Mobile 965".split(";");function Io(a,b,c){this.a=a;this.g=b;this.f=c;this.h=this.a.createTexture();this.v=this.u=10497;this.s=9986;this.o=9729;this.c=0;this.b=3553;this.i=this.j=0;this.m=!1;this.l=34069}function Jo(a,b){a.c!=b&&(a.c=b)}Io.prototype.bind=function(){3553==this.b?this.f.xa(this.c,this):this.f.Vb(this.c,this)};function Ko(a,b){a.u!=b&&(a.bind(),a.a.texParameteri(a.b,10242,b),a.u=b)}function Lo(a,b){a.v!=b&&(a.bind(),a.a.texParameteri(a.b,10243,b),a.v=b)}function Mo(a,b){Ko(a,b);Lo(a,b)} +function No(a,b){a.s!=b&&(a.bind(),a.a.texParameteri(a.b,10241,b),a.s=b)}function Oo(a,b){a.o!=b&&(a.bind(),a.a.texParameteri(a.b,10240,b),a.o=b)}Io.prototype.deleteTexture=function(){for(var a=Po(this.g),b=0;b<=this.f.vb();++b)Jo(this,b),3553==this.b?this.f.c[this.c]==this&&this.f.xa(this.c,null):this.f.g[this.c]==this&&this.f.Vb(this.c,null);this.m=!0;this.a.deleteTexture(this.h);this.g.Rb(a)}; +function Qo(a,b,c,d,e){Ro(a,b.width,b.height,c,d,e);var f=So(a);a.bind();To(a,b.width,c,d);a.a.texImage2D(f,e,c,c,d,b);a.g.ub(3317)}function Uo(a,b,c,d,e,f,g){Ro(a,c,d,e,f,g);var h=So(a);a.bind();To(a,c,e,f);a.a.texImage2D(h,g,e,c,d,0,e,f,b);a.g.ub(3317)}function Vo(a,b,c,d,e,f,g,h,k){var l=So(a);a.bind();a.a.texSubImage2D(l,k,c,d,e,f,g,h,b)}function Ro(a,b,c,d,e,f){0!=f||b==a.j&&c==a.i&&d==a.A&&e==a.B||(a.j=b,a.i=c)}function So(a){return 34067==a.b?a.l:a.b} +var Wo={6408:4,6407:3,6410:2,6409:1,6406:1},Xo={5121:1,5126:4,32819:2,33635:2,32820:2};function To(a,b,c,d){b*=(5121==d||5126==d?Wo[c]:1)*Xo[d];0!=b%4&&(c=1,0==b%2&&(c=2),a.g.eb(3317,c))};function Yo(){this.h=this.f=this.i=this.b=void 0;this.c=[];this.g=[]}r=Yo.prototype;r.clear=function(){this.de();this.pe();this.qe();this.ve();for(var a=31;0<=a;--a)this.ye(a),this.ze(a)};r.apply=function(a){void 0!==a.b&&a.b!==this.b&&this.Ua(a.b);void 0!==a.i&&a.i!==this.i&&this.Jc(a.i);void 0!==a.f&&a.f!==this.f&&this.lc(a.f);void 0!==a.h&&a.h!==this.h&&this.Oc(a.h);for(var b=31;0<=b;--b)void 0!==a.c[b]&&a.c[b]!==this.c[b]&&this.xa(b,a.c[b]),void 0!==a.g[b]&&a.g[b]!==this.g[b]&&this.Vb(b,a.g[b])}; +r.vb=function(){return 32};r.Ua=function(a){this.b=a};r.de=function(){this.b=void 0};r.Jc=function(a){this.i=a};r.pe=function(){this.i=void 0};r.lc=function(a){this.f=a};r.qe=function(){this.f=void 0};r.Oc=function(a){this.h=a};r.ve=function(){this.h=void 0};r.xa=function(a,b){this.c[a]=b};r.ye=function(a){delete this.c[a]};r.Vb=function(a,b){this.g[a]=b};r.ze=function(a){delete this.g[a]};function Zo(a,b){Yo.call(this);this.a=a;this.l=Math.min(32,a.getParameter(35661));this.m=b;this.j=zc||sb&&!Ab("536.3");a=this.a;this.a=null;this.clear();this.a=a}F(Zo,Yo);r=Zo.prototype;r.Ua=function(a){if(this.j||this.b!==a)Zo.R.Ua.call(this,a),this.a&&this.a.bindBuffer(34962,a)};r.de=function(){this.Ua(null)};r.Jc=function(a){if(this.j||this.i!==a)Zo.R.Jc.call(this,a),this.a&&this.a.bindBuffer(34963,a)};r.pe=function(){this.Jc(null)}; +r.lc=function(a){if(this.j||this.f!==a)Zo.R.lc.call(this,a),this.a&&this.a.bindFramebuffer(36160,a)};r.qe=function(){this.lc(null)};r.Oc=function(a){if(this.j||this.h!==a)Zo.R.Oc.call(this,a),this.a&&this.a.bindRenderbuffer(36161,a)};r.ve=function(){this.Oc(null)};r.xa=function(a,b){a<this.l&&this.m.Rb(33984+a);if(this.j||this.c[a]!==b)Zo.R.xa.call(this,a,b),this.a&&(b?this.a.bindTexture(3553,b.h):this.a.bindTexture(3553,null))};r.ye=function(a){this.xa(a,null)}; +r.Vb=function(a,b){a<this.l&&this.m.Rb(33984+a);if(this.j||this.g[a]!==b)Zo.R.Vb.call(this,a,b),this.a&&(b?this.a.bindTexture(34067,b.h):this.a.bindTexture(34067,null))};r.ze=function(a){this.Vb(a,null)};r.vb=function(){return this.l-1};function $o(){this.h=new ArrayBuffer(ap);this.c=new Uint8Array(this.h);this.b=new Uint16Array(this.h);this.i=new Uint32Array(this.h);this.f=new Int32Array(this.h);this.a=new Float32Array(this.h);this.clear()} +$o.prototype.clear=function(){this.tb(3042);this.tb(2884);this.tb(2929);this.tb(3024);this.tb(32823);this.tb(32926);this.tb(32928);this.tb(3089);this.tb(2960);this.ee();this.fe();this.ge();this.me();this.we();this.he();this.ie();this.je();this.ke();this.ne();this.oe();this.xe();this.Ge();this.le();this.re();this.te();this.ue();for(var a=0;32>a;++a)this.Ae(a);this.ce();this.ub(3317);this.ub(3333);this.ub(37440);this.ub(37441);this.ub(37443);this.se(33170)}; +$o.prototype.apply=function(a){bp(a,3042)&&cp(a,3042)!=cp(this,3042)&&this.Ta(3042,cp(a,3042));bp(a,2884)&&cp(a,2884)!=cp(this,2884)&&this.Ta(2884,cp(a,2884));bp(a,2929)&&cp(a,2929)!=cp(this,2929)&&this.Ta(2929,cp(a,2929));bp(a,3024)&&cp(a,3024)!=cp(this,3024)&&this.Ta(3024,cp(a,3024));bp(a,32823)&&cp(a,32823)!=cp(this,32823)&&this.Ta(32823,cp(a,32823));bp(a,32926)&&cp(a,32926)!=cp(this,32926)&&this.Ta(32926,cp(a,32926));bp(a,32928)&&cp(a,32928)!=cp(this,32928)&&this.Ta(32928,cp(a,32928));bp(a,3089)&& +cp(a,3089)!=cp(this,3089)&&this.Ta(3089,cp(a,3089));bp(a,2960)&&cp(a,2960)!=cp(this,2960)&&this.Ta(2960,cp(a,2960));if(0<=a.a[3]){var b=a.a[3],c=a.a[4],d=a.a[5],e=a.a[6];this.a[3]==b&&this.a[4]==c&&this.a[5]==d&&this.a[6]==e||this.Bc(b,c,d,e)}65535==a.b[14]||dp(this,!1)==dp(a,!1)&&dp(this,!0)==dp(a,!0)||(b=dp(a,!1),c=dp(a,!0),c==b&&(c=void 0),this.jc(b,c));65535!=a.b[16]&&(b=a.b[16],c=a.b[17],d=a.b[18],e=a.b[19],this.b[16]!=b||this.b[17]!=c||this.b[18]!=d||this.b[19]!=e)&&(d==b&&e==c&&(e=d=void 0), +this.kc(b,c,d,e));65535!=a.b[20]&&ep(a)!=ep(this)&&this.Hc(ep(a));0<a.c[48]&&(b=a.a[11],c=2==a.c[48],this.a[11]==b&&this.c[48]==(c?2:1)||this.Pc(b,c));0<=a.a[13]&&(b=a.a[13],c=a.a[14],d=a.a[15],e=a.a[16],this.a[13]==b&&this.a[14]==c&&this.a[15]==d&&this.a[16]==e||this.Cc(b,c,d,e));0<=a.a[17]&&fp(a)!=fp(this)&&this.Dc(fp(a));1==a.c[76]&&gp(a)!=gp(this)&&this.Ec(gp(a));0<a.c[80]&&(b=2==a.c[80],c=2==a.c[81],d=2==a.c[82],e=2==a.c[83],hp(this,b,c,d,e)||this.Fc(b,c,d,e));0<a.c[84]&&ip(a)!=ip(this)&&this.Fb(ip(a)); +0<=a.a[jp]&&(b=a.a[jp],c=a.a[jp+1],this.a[jp]==b&&this.a[jp+1]==c||this.Ic(b,c));0<=a.f[kp+2]&&(b=a.f[kp],c=a.f[kp+1],d=a.f[kp+2],e=a.f[kp+3],this.f[kp]==b&&this.f[kp+1]==c&&this.f[kp+2]==d&&this.f[kp+3]==e||this.Qc(b,c,d,e));0<=a.f[lp+2]&&(b=a.f[lp],c=a.f[lp+1],d=a.f[lp+2],e=a.f[lp+3],this.f[lp]==b&&this.f[lp+1]==c&&this.f[lp+2]==d&&this.f[lp+3]==e||this.nc(b,c,d,e));65535!=a.b[mp]&&np(a)!=np(this)&&this.Gc(np(a));65535!=a.b[op]&&pp(a)!=pp(this)&&this.Kc(pp(a));0<a.a[qp]&&rp(a)!=rp(this)&&this.Mc(rp(a)); +0<a.c[sp]&&(b=a.a[tp],c=a.a[tp+1],0<this.c[sp]&&this.a[tp]==b&&this.a[tp+1]==c||this.Nc(b,c));for(b=0;32>b;++b)0<a.c[up+b]&&vp(a,b)!=vp(this,b)&&this.mc(b,vp(a,b));65535!=a.b[wp]&&Po(a)!=Po(this)&&this.Rb(Po(a));xp(a,3317)&&yp(a,3317)!=yp(this,3317)&&this.eb(3317,yp(a,3317));xp(a,3333)&&yp(a,3333)!=yp(this,3333)&&this.eb(3333,yp(a,3333));xp(a,37440)&&yp(a,37440)!=yp(this,37440)&&this.eb(37440,yp(a,37440));xp(a,37441)&&yp(a,37441)!=yp(this,37441)&&this.eb(37441,yp(a,37441));xp(a,37443)&&yp(a,37443)!= +yp(this,37443)&&this.eb(37443,yp(a,37443));65535!=a.b[zp]&&Ap(a)!=Ap(this)&&this.Lc(33170,Ap(a))};var Bp=[];Bp[3042]=0;Bp[2884]=1;Bp[2929]=2;Bp[3024]=3;Bp[32823]=4;Bp[32926]=5;Bp[32928]=6;Bp[3089]=7;Bp[2960]=8;r=$o.prototype;r.Ta=function(a,b){this.c[0+Bp[a]]=b?2:1};function cp(a,b){a=a.c[0+Bp[b]];if(0!=a)return 2==a}function bp(a,b){return 0<a.c[0+Bp[b]]}r.tb=function(a){this.c[0+Bp[a]]=0};r.Bc=function(a,b,c,d){this.a[3]=a;this.a[4]=b;this.a[5]=c;this.a[6]=d}; +r.ee=function(){this.a[3]=-1;this.a[4]=-1;this.a[5]=-1;this.a[6]=-1};r.jc=function(a,b){this.b[14]=a;this.b[15]=b||a};function dp(a,b){a=b?a.b[15]:a.b[14];if(65535!=a)return a}r.fe=function(){this.b[14]=65535;this.b[15]=65535};r.kc=function(a,b,c,d){this.b[16]=a;this.b[17]=b;this.b[18]=void 0===c?a:c;this.b[19]=void 0===d?b:d};r.ge=function(){this.b[16]=65535;this.b[17]=65535;this.b[18]=65535;this.b[19]=65535};r.Hc=function(a){this.b[20]=a};function ep(a){a=a.b[20];if(65535!=a)return a} +r.me=function(){this.b[20]=65535};r.Pc=function(a,b){this.a[11]=a;this.c[48]=b?2:1};r.we=function(){this.c[48]=0};r.Cc=function(a,b,c,d){this.a[13]=a;this.a[14]=b;this.a[15]=c;this.a[16]=d};r.he=function(){this.a[13]=-1;this.a[14]=-1;this.a[15]=-1;this.a[16]=-1};r.Dc=function(a){this.a[17]=a};function fp(a){a=a.a[17];if(!(0>a))return a}r.ie=function(){this.a[17]=-1};r.Ec=function(a){this.i[18]=a;this.c[76]=1};function gp(a){if(1==a.c[76])return a.i[18]}r.je=function(){this.c[76]=0}; +r.Fc=function(a,b,c,d){this.c[80]=a?2:1;this.c[81]=b?2:1;this.c[82]=c?2:1;this.c[83]=d?2:1};r.ke=function(){this.c[80]=0;this.c[81]=0;this.c[82]=0;this.c[83]=0};function hp(a,b,c,d,e){return a.c[80]==(b?2:1)&&a.c[81]==(c?2:1)&&a.c[82]==(d?2:1)&&a.c[83]==(e?2:1)}r.Fb=function(a){this.c[84]=a?2:1};function ip(a){a=a.c[84];if(0!=a)return 2==a}r.ne=function(){this.c[84]=0};var Cp=96,jp=22;$o.prototype.Ic=function(a,b){this.a[jp]=a;this.a[jp+1]=b}; +$o.prototype.oe=function(){this.a[jp]=-1;this.a[jp+1]=-1};var Dp=Cp+16,kp=Cp/4;$o.prototype.Qc=function(a,b,c,d){this.f[kp]=a;this.f[kp+1]=b;this.f[kp+2]=c;this.f[kp+3]=d};$o.prototype.xe=function(){this.f[kp+2]=-1;this.f[kp+3]=-1};var Ep=Dp+16,lp=Dp/4;$o.prototype.nc=function(a,b,c,d){this.f[lp]=a;this.f[lp+1]=b;this.f[lp+2]=c;this.f[lp+3]=d};function Fp(a){var b=a.f[lp+2];if(!(0>b))return[a.f[lp],a.f[lp+1],b,a.f[lp+3]]}$o.prototype.Ge=function(){this.f[lp+2]=-1;this.f[lp+3]=-1}; +var Gp=Ep+4,mp=Ep/2;$o.prototype.Gc=function(a){this.b[mp]=a};function np(a){a=a.b[mp];if(65535!=a)return a}$o.prototype.le=function(){this.b[mp]=65535};var Hp=Gp+4,op=Gp/2;$o.prototype.Kc=function(a){this.b[op]=a};function pp(a){a=a.b[op];if(65535!=a)return a}$o.prototype.re=function(){this.b[op]=65535};var Ip=Hp+4,qp=Hp/4;$o.prototype.Mc=function(a){this.a[qp]=a};function rp(a){a=a.a[qp];if(!(0>a))return a}$o.prototype.te=function(){this.a[qp]=-1};var up=Ip+12,tp=Ip/4,sp=Ip+8; +$o.prototype.Nc=function(a,b){this.a[tp]=a;this.a[tp+1]=b;this.c[sp]=1};$o.prototype.ue=function(){this.c[sp]=0};var Jp=up+32;$o.prototype.mc=function(a,b){this.c[up+a]=b?2:1};function vp(a,b){a=a.c[up+b];if(0!=a)return 2==a}$o.prototype.Ae=function(a){this.c[up+a]=0};var Kp=Jp+4,wp=Jp/2;$o.prototype.Rb=function(a){this.b[wp]=a};function Po(a){a=a.b[wp];if(65535!=a)return a}$o.prototype.ce=function(){this.b[wp]=65535};var Lp=[];Lp[3317]=0;Lp[3333]=1;Lp[37440]=2;Lp[37441]=3;Lp[37443]=4; +var Mp=Kp+12,Np=Kp/2;$o.prototype.eb=function(a,b){this.b[Np+Lp[a]]=b};function yp(a,b){a=a.b[Np+Lp[b]];if(65535!=a)return a}function xp(a,b){return 65535!=a.b[Np+Lp[b]]}$o.prototype.ub=function(a){this.b[Np+Lp[a]]=65535};var ap=Mp+4,zp=Mp/2;$o.prototype.Lc=function(a,b){this.b[zp]=b};function Ap(a){a=a.b[zp];if(65535!=a)return a}$o.prototype.se=function(){this.b[zp]=65535};function Op(a){this.g=a;a.scissor(0,0,0,0);a.viewport(0,0,0,0);a.enableVertexAttribArray(0);a=this.g;this.g=null;$o.call(this);this.g=a}F(Op,$o);r=Op.prototype;r.Ta=function(a,b){if(cp(this,a)!=b){Op.R.Ta.call(this,a,b);var c=this.g;c&&(b?c.enable(a):c.disable(a))}};r.tb=function(a){3024==a?this.Ta(a,!0):this.Ta(a,!1)};r.Bc=function(a,b,c,d){if(this.a[3]!=a||this.a[4]!=b||this.a[5]!=c||this.a[6]!=d){Op.R.Bc.call(this,a,b,c,d);var e=this.g;e&&e.blendColor(a,b,c,d)}};r.ee=function(){this.Bc(0,0,0,0)}; +r.jc=function(a,b){var c=void 0===b?a:b;if(dp(this,!1)!=a||dp(this,!0)!=c)Op.R.jc.call(this,a,b),(b=this.g)&&(c==a?b.blendEquation(a):b.blendEquationSeparate(a,c))};r.fe=function(){this.jc(32774)};r.kc=function(a,b,c,d){var e=void 0===c?a:c,f=void 0===d?b:d;if(this.b[16]!=a||this.b[17]!=b||this.b[18]!=e||this.b[19]!=f)Op.R.kc.call(this,a,b,c,d),(c=this.g)&&(e==a&&f==b?c.blendFunc(a,b):c.blendFuncSeparate(a,b,e,f))};r.ge=function(){this.kc(1,0)}; +r.Hc=function(a){if(ep(this)!=a){Op.R.Hc.call(this,a);var b=this.g;b&&b.depthFunc(a)}};r.me=function(){this.Hc(513)};r.Pc=function(a,b){if(this.a[11]!=a||this.c[48]!=(b?2:1)){Op.R.Pc.call(this,a,b);var c=this.g;c&&c.sampleCoverage(a,b)}};r.we=function(){this.Pc(1,!1)};r.Cc=function(a,b,c,d){if(this.a[13]!=a||this.a[14]!=b||this.a[15]!=c||this.a[16]!=d){Op.R.Cc.call(this,a,b,c,d);var e=this.g;e&&e.clearColor(a,b,c,d)}};r.he=function(){this.Cc(0,0,0,0)}; +r.Dc=function(a){if(fp(this)!=a){Op.R.Dc.call(this,a);var b=this.g;b&&b.clearDepth(a)}};r.ie=function(){this.Dc(1)};r.Ec=function(a){if(gp(this)!=a){Op.R.Ec.call(this,a);var b=this.g;b&&b.clearStencil(a)}};r.je=function(){this.Ec(0)};r.Fc=function(a,b,c,d){if(!hp(this,a,b,c,d)){Op.R.Fc.call(this,a,b,c,d);var e=this.g;e&&e.colorMask(a,b,c,d)}};r.ke=function(){this.Fc(!0,!0,!0,!0)};r.Fb=function(a){if(ip(this)!=a){Op.R.Fb.call(this,a);var b=this.g;b&&b.depthMask(a)}};r.ne=function(){this.Fb(!0)}; +r.Ic=function(a,b){if(this.a[jp]!=a||this.a[jp+1]!=b){Op.R.Ic.call(this,a,b);var c=this.g;c&&c.depthRange(a,b)}};r.oe=function(){this.Ic(0,1)};r.Qc=function(a,b,c,d){if(this.f[kp]!=a||this.f[kp+1]!=b||this.f[kp+2]!=c||this.f[kp+3]!=d){Op.R.Qc.call(this,a,b,c,d);var e=this.g;e&&e.scissor(a,b,c,d)}};r.xe=function(){this.Qc(0,0,0,0)};r.nc=function(a,b,c,d){if(this.f[lp]!=a||this.f[lp+1]!=b||this.f[lp+2]!=c||this.f[lp+3]!=d){Op.R.nc.call(this,a,b,c,d);var e=this.g;e&&e.viewport(a,b,c,d)}}; +r.Ge=function(){this.nc(0,0,0,0)};r.Gc=function(a){if(np(this)!=a){Op.R.Gc.call(this,a);var b=this.g;b&&b.cullFace(a)}};r.le=function(){this.Gc(1029)};r.Kc=function(a){if(pp(this)!=a){Op.R.Kc.call(this,a);var b=this.g;b&&b.frontFace(a)}};r.re=function(){this.Kc(2305)};r.Mc=function(a){if(rp(this)!=a){Op.R.Mc.call(this,a);var b=this.g;b&&b.lineWidth(a)}};r.te=function(){this.Mc(1)}; +r.Nc=function(a,b){if(!(0<this.c[sp])||this.a[tp]!=a||this.a[tp+1]!=b){Op.R.Nc.call(this,a,b);var c=this.g;c&&c.polygonOffset(a,b)}};r.ue=function(){this.Nc(0,0)};r.mc=function(a,b){if(vp(this,a)!=b){Op.R.mc.call(this,a,b);var c=this.g;c&&(b?c.enableVertexAttribArray(a):c.disableVertexAttribArray(a))}};r.Ae=function(a){this.mc(a,!1)};r.Rb=function(a){if(Po(this)!=a){$o.prototype.Rb.call(this,a);var b=this.g;b&&b.activeTexture(a)}};r.ce=function(){this.Rb(33984)}; +r.eb=function(a,b){if(yp(this,a)!=b){Op.R.eb.call(this,a,b);var c=this.g;c&&c.pixelStorei(a,b)}};r.ub=function(a){switch(a){case 3317:case 3333:this.eb(a,4);break;case 37440:case 37441:this.eb(a,0);break;default:this.eb(a,37444)}};r.Lc=function(a,b){if(Ap(this)!=b){Op.R.Lc.call(this,a,b);var c=this.g;c&&c.hint(a,b)}};r.se=function(a){this.Lc(a,4352)};function Pp(){this.Ka=!1;this.Da=this.M=null}Pp.prototype.O=function(){return this.Ka};Pp.prototype.$=function(){if(!this.Ka){this.Ka=!0;this.X();if(this.M){for(var a=0;a<this.M.length;++a)this.M[a].$();this.M=null}if(this.Da){for(a=0;a<this.Da.length;++a)this.Da[a]();this.Da=null}}};function Qp(a,b){a.M||(a.M=[]);a.M.push(b)}Pp.prototype.X=function(){};function Rp(){this.c=[0,0];this.a=[0,0];this.h=0;this.g=this.b=null;this.f={}}function Sp(a,b,c,d,e,f,g){this.handle=a;this.b=b;this.g=c;this.h=d;this.a=null;this.next=e;this.c=f;this.f=g}function Tp(a,b,c){a.c[0]=B(b)?b:a.c[0];a.c[1]=B(c)?c:a.c[1];Up(a)}Rp.prototype.add=function(a,b,c,d,e){c=c||0;d=d||0;if(c>this.c[0]||d>this.c[1])return-1;var f=this.h++;a=new Sp(f,a,b,e||null,this.b,c,d);this.f[f]=a;this.b&&(this.b.a=a);this.b=a;this.a[0]+=c;this.a[1]+=d;null==this.g&&(this.g=a);Up(this);return f}; +Rp.prototype.get=function(a){return(a=this.f[a])?a.b:void 0};function Up(a){for(var b=a.g;b&&(a.a[0]>a.c[0]||a.a[1]>a.c[1]);){var c=b;b=b.a;if(a.a[0]>a.c[0]&&0<c.c||a.a[1]>a.c[1]&&0<c.f||0==c.c&&0==c.f)c.g&&c.g.call(c.h,c.handle,c.b,!1),Vp(a,c.handle)}}function Wp(a,b){(b=a.f[b])&&b.a&&((b.a.next=b.next)?b.next.a=b.a:a.g=b.a,b.a=null,b.next=a.b,a.b.a=b,a.b=b)} +function Vp(a,b){var c=a.f[b];c&&(c.a?c.a.next=c.next:a.b=c.next,c.next?c.next.a=c.a:a.g=c.a,c.a=c.next=c.b=null,c.handle=-1,delete a.f[b],a.a[0]-=c.c,a.a[1]-=c.f)}Rp.prototype.clear=function(){for(;this.b;){var a=this.b;a.g.call(a.h,a.handle,a.b,!0);Vp(this,a.handle)}};function Xp(a,b,c){this.a=new Rp;this.j=a;this.i=this.m=0;this.o=1;this.h=this.u=this.g=this.s=0;this.b=[];this.f=[];this.c=[];this.v=D(this.l,this,this.f);D(this.l,this,this.b);D(this.l,this,this.c);Yp(this);var d=this;lo(function(a){d.o=a?1:.5;Yp(d)},c,b)}F(Xp,Pp);Xp.prototype.X=function(){this.clear();Zp(this);Xp.R.X.call(this)};Xp.prototype.clear=function(){this.a.clear()};function $p(a,b,c,d,e){return a.a.add(b,c,d,e)} +Xp.prototype.createTexture=function(a){var b=this.j,c=b.createTexture();b.bindTexture(3553,c);b.texParameteri(3553,10241,a);b.texParameteri(3553,10240,a);b.texParameteri(3553,10242,33071);b.texParameteri(3553,10243,33071);return this.a.add(c,this.v,0,1)};function Yp(a){var b=100*(.75*a.i+.25*a.m);b=Math.max(48E6,b*a.o);var c=Math.max(200,.002*a.i*a.o);a.s=.1*b;a.u=.1*c;Tp(a.a,b,c)} +Xp.prototype.l=function(a,b,c){var d=this.a.f[b];this.g+=d&&d.c;b=this.a.f[b];this.h+=b&&b.f;a.push(c);(this.g>=this.s||this.h>=this.u)&&Zp(this)};function Zp(a){for(var b=0;b<a.b.length;b++)a.j.deleteBuffer(a.b[b]);for(b=0;b<a.f.length;b++)a.j.deleteTexture(a.f[b]);for(b=0;b<a.c.length;b++)a.j.deleteRenderbuffer(a.c[b]);a.g=0;a.h=0;a.b.splice(0,a.b.length);a.f.splice(0,a.f.length);a.c.splice(0,a.c.length)};function aq(a){Ja.call(this,a)}F(aq,Ja);aq.prototype.name="LostContextError";function bq(a,b){this.c=a.createProgram();this.b=a;this.l=b;this.m=[];this.g=!0;this.f=[];this.j=[];this.a=[];this.h={};this.i={}}r=bq.prototype;r.Bd=function(){this.l.f!=this&&(this.l.f=this,this.b.useProgram(this.c))};r.attachShader=function(a){this.m.push(a);this.b.attachShader(this.c,a)};r.detachShader=function(a){Ta(this.m,a);this.b.detachShader(this.c,a)};r.bindAttribLocation=function(a,b){this.b.bindAttribLocation(this.c,a,b);this.i[b]=a}; +r.getAttribLocation=function(a){var b=this.i[a];void 0===b&&(b=this.b.getAttribLocation(this.c,a),this.i[a]=b);return b};r.deleteProgram=function(){this.b.deleteProgram(this.c)};r.getParameter=function(a){return this.b.getProgramParameter(this.c,a)};r.Cd=function(){this.b.linkProgram(this.c);this.g=!1}; +function cq(a){a.g=!0;a.i={};a.f=[];a.a=[];a.h={};for(var b=a.b.getProgramParameter(a.c,35718),c=0,d,e=0;e<b;++e){var f=a.b.getActiveUniform(a.c,e);if(0<=f.name.indexOf("[")){var g=f.name.substr(0,f.name.indexOf("[")),h=f.size;a.h[g]=c;for(var k=0;k<h;++k){d=c++;var l=g+"["+k+"]";a.h[l]=d;a.j[d]=h-k;a.f[d]=a.b.getUniformLocation(a.c,l);a.a[d]=dq(f.type)}}else d=c++,a.h[f.name]=d,a.j[d]=0,a.f[d]=a.b.getUniformLocation(a.c,f.name),a.a[d]=dq(f.type)}} +r.getActiveUniform=function(a){return this.b.getActiveUniform(this.c,a)};r.getUniformLocation=function(a){this.g||cq(this);return void 0!==this.h[a]?this.h[a]:-1};r.Ve=function(a,b){this.g||cq(this);var c=this.f,d=this.a,e=this.b;-1!=a&&b!=d[a]&&(d[a]=b,e.uniform1f(c[a],b))};r.Xe=function(a,b,c){this.g||cq(this);var d=this.f,e=this.b;if(-1!=a){var f=this.a[a];if(b!=f[0]||c!=f[1])f[0]=b,f[1]=c,e.uniform2f(d[a],b,c)}}; +r.$e=function(a,b,c,d,e){this.g||cq(this);var f=this.f,g=this.b;if(-1!=a){var h=this.a[a];if(b!=h[0]||c!=h[1]||d!=h[2]||e!=h[3])h[0]=b,h[1]=c,h[2]=d,h[3]=e,g.uniform4f(f[a],b,c,d,e)}};r.We=function(a,b){this.g||cq(this);var c=this.f,d=this.a,e=this.b;if(-1!=a){var f=b;"boolean"==typeof d[a]&&(f=!!b);f!=d[a]&&(d[a]=f,e.uniform1i(c[a],b))}}; +r.Ye=function(a,b){this.g||cq(this);if(-1!=a){var c=!1,d;for(d=0;!c&&d<b.length/2;++d)c=b[2*d]!=this.a[a+d][0]||b[2*d+1]!=this.a[a+d][1];if(c){for(d=0;d<b.length/2;++d)this.a[a+d][0]=b[2*d],this.a[a+d][1]=b[2*d+1];this.b.uniform2fv(this.f[a],b)}}}; +r.Ze=function(a,b){this.g||cq(this);if(-1!=a){var c=!1,d;for(d=0;!c&&d<b.length/3;++d)c=b[3*d]!=this.a[a+d][0]||b[3*d+1]!=this.a[a+d][1]||b[3*d+2]!=this.a[a+d][2];if(c){for(d=0;d<b.length/3;++d)this.a[a+d][0]=b[3*d],this.a[a+d][1]=b[3*d+1],this.a[a+d][2]=b[3*d+2];this.b.uniform3fv(this.f[a],b)}}}; +r.af=function(a,b){this.g||cq(this);if(-1!=a){var c=!1,d;for(d=0;!c&&d<b.length/4;++d)c=b[4*d]!=this.a[a+d][0]||b[4*d+1]!=this.a[a+d][1]||b[4*d+2]!=this.a[a+d][2]||b[4*d+3]!=this.a[a+d][3];if(c){for(d=0;d<b.length/4;++d)this.a[a+d][0]=b[4*d],this.a[a+d][1]=b[4*d+1],this.a[a+d][2]=b[4*d+2],this.a[a+d][3]=b[4*d+3];this.b.uniform4fv(this.f[a],b)}}}; +r.bf=function(a,b,c){this.g||cq(this);if(-1!=a){var d=!1;for(b=0;!d&&b<c.length/16;++b){d=16*b;var e=this.a[a+b];d=c[d]!=e[0]||c[d+1]!=e[1]||c[d+2]!=e[2]||c[d+3]!=e[3]||c[d+4]!=e[4]||c[d+5]!=e[5]||c[d+6]!=e[6]||c[d+7]!=e[7]||c[d+8]!=e[8]||c[d+9]!=e[9]||c[d+10]!=e[10]||c[d+11]!=e[11]||c[d+12]!=e[12]||c[d+13]!=e[13]||c[d+14]!=e[14]||c[d+15]!=e[15]}if(d){for(b=0;b<c.length/16;++b){e=this.a[a+b];d=16*b;for(var f=0;16>f;++f)e[f]=c[d+f]}this.b.uniformMatrix4fv(this.f[a],!1,c)}}}; +function dq(a){switch(a){case 35670:return!1;case 5124:case 5126:case 35678:case 35680:return 0;case 35664:return new Float32Array(2);case 35667:return new Int32Array(2);case 35671:return[!1,!1];case 35665:return new Float32Array(3);case 35668:return new Int32Array(3);case 35672:return[!1,!1,!1];case 35666:return new Float32Array(4);case 35669:return new Int32Array(4);case 35673:return[!1,!1,!1,!1];case 35674:return new Float32Array(4);case 35675:return new Float32Array(9);case 35676:return new Float32Array(16)}return null} +;function eq(a,b){rc.call(this);this.B=fq++;this.j=a;this.c=b;this.b=new Op(this.c);this.a=new Zo(this.c,this.b);this.v=new no(this);Jb(this,this.v);this.h=new Xp(this,void 0,this.v);Jb(this,this.h);this.f=null;this.m=this.s=this.g=void 0;this.i=this.getParameter(3379);this.getParameter(34076);this.l=void 0;po(this.v,a,"webglcontextlost",this.Ff,!1,this);po(this.v,a,"webglcontextrestored",this.Gf,!1,this);gq(this);this.A=0}F(eq,rc);var fq=0;r=eq.prototype;r.wa=function(){return this.B}; +function hq(a){a.A=1;return a.c}function iq(a){a.A&1&&(a.f=null);a.A=0}r.X=function(){this.f=null;this.c.useProgram(null);eq.R.X.call(this)};function gq(a){var b=(a.c.drawingBufferWidth||a.j.a.width)*(a.c.drawingBufferHeight||a.j.a.height),c=a.j.c;a=a.h;c=b/(c*c);if(b!=a.m||c!=a.i)a.m=b,a.i=c,Yp(a)}function jq(a,b){var c=Po(a.b)-33984;3553==b?(a=a.a.c[c],3553!=a.b&&(a.b=3553)):(a=a.a.g[c],34067!=a.b&&(a.b=34067),34067!=b&&(a.l=b));return a} +r.texImage2D=function(a,b,c,d,e,f,g,h,k){g?Uo(jq(this,a),k,d,e,g,h,b):Qo(jq(this,a),f,d,e,b)};r.texSubImage2D=function(a,b,c,d,e,f,g,h,k){h?Vo(jq(this,a),k,c,d,e,f,g,h,b):(a=jq(this,a),h=So(a),a.bind(),To(a,g.width,e,f),a.a.texSubImage2D(h,b,c,d,e,f,g),a.g.ub(3317))};r.compressedTexImage2D=function(a,b,c,d,e,f,g){a=jq(this,a);Ro(a,d,e,c,0,b);f=So(a);a.bind();a.a.compressedTexImage2D(f,b,c,d,e,0,g)};r.activeTexture=function(a){this.b.Rb(a)};r.blendColor=function(a,b,c,d){this.b.Bc(a,b,c,d)}; +r.blendEquation=function(a){this.b.jc(a)};r.blendEquationSeparate=function(a,b){this.b.jc(a,b)};r.blendFunc=function(a,b){this.b.kc(a,b)};r.blendFuncSeparate=function(a,b,c,d){this.b.kc(a,b,c,d)};r.clearColor=function(a,b,c,d){this.b.Cc(a,b,c,d)};r.clearDepth=function(a){this.b.Dc(a)};r.clearStencil=function(a){this.b.Ec(a)};r.colorMask=function(a,b,c,d){this.b.Fc(a,b,c,d)};r.cullFace=function(a){this.b.Gc(a)};r.depthFunc=function(a){this.b.Hc(a)};r.depthMask=function(a){this.b.Fb(a)}; +r.depthRange=function(a,b){this.b.Ic(a,b)};r.disable=function(a){this.b.Ta(a,!1)};r.disableVertexAttribArray=function(a){this.b.mc(a,!1)};r.enable=function(a){this.b.Ta(a,!0)};r.enableVertexAttribArray=function(a){this.b.mc(a,!0)};r.frontFace=function(a){this.b.Kc(a)};r.hint=function(a,b){this.b.Lc(a,b)};r.lineWidth=function(a){this.b.Mc(a)};r.pixelStorei=function(a,b){this.b.eb(a,b)};r.polygonOffset=function(a,b){this.b.Nc(a,b)};r.sampleCoverage=function(a,b){this.b.Pc(a,b)}; +r.scissor=function(a,b,c,d){this.b.Qc(a,b,c,d)};r.stencilFunc=function(a,b,c){this.c.stencilFunc(a,b,c)};r.stencilOp=function(a,b,c){this.c.stencilOp(a,b,c)};r.viewport=function(a,b,c,d){gq(this);this.b.nc(a,b,c,d)};r.bindBuffer=function(a,b){34962==a?this.a.Ua(b):this.a.Jc(b)};r.bindFramebuffer=function(a,b){this.a.lc(b)};r.bindRenderbuffer=function(a,b){this.a.Oc(b)};r.bindTexture=function(a,b){var c=Po(this.b)-33984;b&&(b.b!=a&&(b.b=a),Jo(b,c));3553==a?this.a.xa(c,b):this.a.Vb(c,b)}; +r.attachShader=function(a,b){a.attachShader&&a.attachShader(b)};r.bindAttribLocation=function(a,b,c){a.bindAttribLocation&&a.bindAttribLocation(b,c)};r.createProgram=function(){return new bq(this.c,this)};r.deleteProgram=function(a){a.deleteProgram&&a.deleteProgram()};r.detachShader=function(a,b){a.detachShader&&a.detachShader(b)};r.getActiveUniform=function(a,b){return a.getActiveUniform?a.getActiveUniform(b):null}; +r.getAttribLocation=function(a,b){return a.getAttribLocation?a.getAttribLocation(b):-1};r.getProgramParameter=function(a,b){return a.getParameter?a.getParameter(b):-1};r.getUniformLocation=function(a,b){return a.getUniformLocation?a.getUniformLocation(b):-1};r.linkProgram=function(a){a.Cd&&a.Cd()};r.uniform1f=function(a,b){var c=this.f;c&&c.Ve&&c.Ve(a,b)};r.uniform1i=function(a,b){var c=this.f;c&&c.We&&c.We(a,b)};r.uniform2f=function(a,b,c){var d=this.f;d&&d.Xe&&d.Xe(a,b,c)}; +r.uniform2fv=function(a,b){var c=this.f;c&&c.Ye&&c.Ye(a,b)};r.uniform3fv=function(a,b){var c=this.f;c&&c.Ze&&c.Ze(a,b)};r.uniform4f=function(a,b,c,d,e){var f=this.f;f&&f.$e&&f.$e(a,b,c,d,e)};r.uniform4fv=function(a,b){var c=this.f;c&&c.af&&c.af(a,b)};r.uniformMatrix4fv=function(a,b,c){var d=this.f;d&&d.bf&&d.bf(a,b,c)};r.useProgram=function(a){a.Bd&&a.Bd()};r.isContextLost=function(){return this.c.isContextLost()}; +r.getSupportedExtensions=function(){var a=this.c.getSupportedExtensions();if(!a&&this.isContextLost())throw new aq("getSupportedExtensions",this);return a};r.getExtension=function(a){return this.c.getExtension(a)};var kq=["WEBGL_compressed_texture_s3tc","WEBKIT_WEBGL_compressed_texture_s3tc","MOZ_WEBGL_compressed_texture_s3tc"];r=eq.prototype; +r.Zc=function(){if(B(this.g))return!!this.g;if(yc&&!Ab(30))for(var a=this.getSupportedExtensions(),b=kq,c=0;c<a.length;c++)for(var d=0;d<b.length;d++){if(a[c]==b[d]&&(this.g=this.getExtension(b[d])))return!0}else for(b=kq,d=0;d<b.length;d++)if(this.g=this.getExtension(b[d]))return!0;this.g=null;return!1}; +function lq(a){if(B(a.s))return!!a.s;var b=a.getExtension("OES_texture_float");if(b){a.getExtension("OES_texture_float_linear");a.getExtension("WEBGL_color_buffer_float");for(var c=0;8>c;++c)a.disableVertexAttribArray(c);a.disable(3089);a.disable(2960);a.disable(2929);a.disable(3042);a.disable(2884);c=a.createShader(35633);a.shaderSource(c,"attribute vec4 vertexClip;\nvoid main() {\n gl_Position = vec4(vertexClip.xy, 0.0, 1.0);\n}");a.compileShader(c);var d=a.createShader(35632);a.shaderSource(d, +"precision highp float;\nuniform sampler2D sampler;\nuniform float mode;\nvoid main() {\n if (mode == 0.0) {\n gl_FragColor = floor(gl_FragCoord.xyxy);\n } else {\n gl_FragColor = texture2D(sampler, vec2(0.5));\n }\n}\n");a.compileShader(d);var e=a.createProgram();e.attachShader(c);e.attachShader(d);e.Cd();e.Bd();var f=a.createBuffer();a.bindBuffer(34962,f);a.bufferData(34962,new Float32Array([-1,-1,1,1,1,-1,1,1,-1,1,1,1,1,1,1,1]),35044);a.enableVertexAttribArray(e.getAttribLocation("vertexClip")); +a.vertexAttribPointer(e.getAttribLocation("vertexClip"),4,5126,!1,0,0);a.activeTexture(33984);var g=a.createTexture();a.bindTexture(3553,g);a.texParameteri(3553,10241,9729);a.texParameteri(3553,10240,9729);a.texParameteri(3553,10242,33071);a.texParameteri(3553,10243,33071);Uo(jq(a,3553),null,2,2,6408,5126,0);a.bindTexture(3553,null);var h=a.createFramebuffer();a.bindFramebuffer(36160,h);a.framebufferTexture2D(36160,36064,3553,g,0);a.uniform1f(e.getUniformLocation("mode"),0);a.uniform1i(e.getUniformLocation("sampler"), +0);a.viewport(0,0,2,2);a.drawArrays(5,0,4);a.bindFramebuffer(36160,null);a.uniform1f(e.getUniformLocation("mode"),1);a.drawArrays(5,0,4);var k=new Uint8Array([0,0,0,0]);a.readPixels(0,0,1,1,6408,5121,k);a.disableVertexAttribArray(e.getAttribLocation("vertexClip"));a.deleteBuffer(f);a.deleteTexture(g);a.deleteFramebuffer(h);a.detachShader(e,c);a.deleteShader(c);a.detachShader(e,d);a.deleteShader(d);a.deleteProgram(e);if(2<Math.abs(k[0]-127)||2<Math.abs(k[1]-127)||2<Math.abs(k[2]-127))b=null}a.s=b; +return!!b}function mq(a){B(a.l)||(Co()?a.l=a.getExtension("ANGLE_instanced_arrays"):a.l=null);return a.l}r.bufferData=function(a,b,c){this.c.bufferData(a,b,c)};r.bufferSubData=function(a,b,c){this.c.bufferSubData(a,b,c)};r.clear=function(a){this.c.clear(a)};r.compileShader=function(a){this.c.compileShader(a)};r.copyTexImage2D=function(a,b,c,d,e,f,g){a=jq(this,a);Ro(a,f,g,c,5121,b);var h=So(a);a.bind();a.a.copyTexImage2D(h,b,c,d,e,f,g,0)}; +r.copyTexSubImage2D=function(a,b,c,d,e,f,g,h){a=jq(this,a);var k=So(a);a.bind();a.a.copyTexSubImage2D(k,b,c,d,e,f,g,h)};r.createBuffer=function(){return this.c.createBuffer()};r.createFramebuffer=function(){return this.c.createFramebuffer()};r.createRenderbuffer=function(){return this.c.createRenderbuffer()};r.createShader=function(a){return this.c.createShader(a)};r.createTexture=function(){return new Io(this.c,this.b,this.a)};r.deleteBuffer=function(a){this.c.deleteBuffer(a)}; +r.deleteFramebuffer=function(a){this.c.deleteFramebuffer(a)};r.deleteRenderbuffer=function(a){this.c.deleteRenderbuffer(a)};r.deleteShader=function(a){this.c.deleteShader(a)};r.deleteTexture=function(a){a&&a.deleteTexture()};r.drawArrays=function(a,b,c){this.c.drawArrays(a,b,c)};r.framebufferRenderbuffer=function(a,b,c,d){this.c.framebufferRenderbuffer(a,b,c,d)};r.framebufferTexture2D=function(a,b,c,d,e){this.c.framebufferTexture2D(a,b,c,d.h,e)}; +r.getParameter=function(a){switch(a){case 32873:return this.a.c[Po(this.b)-33984];case 34068:return this.a.g[Po(this.b)-33984];case 35725:return this.f}a=this.c.getParameter(a);if(null===a&&this.isContextLost())throw new aq("getParameter",this);return a};r.getError=function(){return this.c.getError()};r.readPixels=function(a,b,c,d,e,f,g){this.c.readPixels(a,b,c,d,e,f,g)};r.renderbufferStorage=function(a,b,c,d){this.c.renderbufferStorage(a,b,c,d)}; +r.shaderSource=function(a,b){this.c.shaderSource(a,b)};r.texParameteri=function(a,b,c){a=jq(this,a);switch(b){case 10241:No(a,c);break;case 10240:Oo(a,c);break;case 10242:Ko(a,c);break;case 10243:Lo(a,c)}};r.vertexAttribPointer=function(a,b,c,d,e,f){this.c.vertexAttribPointer(a,b,c,d,e,f)};function nq(a){a.h.clear();a.f=null;a.a.clear();a.b.clear()}r.Ff=function(a){a.b();nq(this);E();this.dispatchEvent("webglcontextlost")}; +r.Gf=function(){nq(this);if(this.g&&(this.g=void 0,!this.Zc()))throw Error("Lost compressed textures extension.");if(this.s&&(this.s=void 0,!lq(this)))throw Error("Lost texture float extension.");if(this.m&&(this.m=void 0,B(this.m)||(this.m=this.getExtension("WEBGL_depth_texture")),!this.m))throw Error("Lost depth texture extension.");B(this.l)&&(this.l=void 0,mq(this));E();this.dispatchEvent("webglcontextrestored")};function oq(a,b,c,d){this.top=a;this.right=b;this.bottom=c;this.left=d}oq.prototype.ceil=function(){this.top=Math.ceil(this.top);this.right=Math.ceil(this.right);this.bottom=Math.ceil(this.bottom);this.left=Math.ceil(this.left);return this};oq.prototype.floor=function(){this.top=Math.floor(this.top);this.right=Math.floor(this.right);this.bottom=Math.floor(this.bottom);this.left=Math.floor(this.left);return this}; +oq.prototype.round=function(){this.top=Math.round(this.top);this.right=Math.round(this.right);this.bottom=Math.round(this.bottom);this.left=Math.round(this.left);return this};function pq(a,b,c,d){this.left=a;this.top=b;this.width=c;this.height=d}pq.prototype.ceil=function(){this.left=Math.ceil(this.left);this.top=Math.ceil(this.top);this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};pq.prototype.floor=function(){this.left=Math.floor(this.left);this.top=Math.floor(this.top);this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this}; +pq.prototype.round=function(){this.left=Math.round(this.left);this.top=Math.round(this.top);this.width=Math.round(this.width);this.height=Math.round(this.height);return this};function qq(a){this.b=a+15>>4;this.a=new Uint16Array(this.b)}function rq(a,b){var c=a.b;b=b+15>>4;var d=a.a,e=new Uint16Array(b);c=b>c?c:b;for(var f=0;f<c;f++)e[f]=d[f];a.b=b;a.a=e}function sq(a,b){return(4294967295<<a&4294967295>>>32-b-1)>>>0}function tq(a){for(var b=0;32>b;b++)if(a&1<<b)return b;return 0}function uq(a){for(var b=0;b<a.b;b++)a.a[b]=0} +function vq(a,b,c){var d=b>>4,e=c-1>>4;b&=15;c=c-1&15;if(d==e)a.a[d]|=sq(b,c);else{a.a[d]|=sq(b,15);for(d+=1;d<e;d++)a.a[d]=65535;a.a[e]|=sq(0,c)}}function wq(a,b,c){var d=b>>4,e=c-1>>4;b&=15;c=c-1&15;if(d==e)a.a[d]&=~sq(b,c);else{a.a[d]&=~sq(b,15);for(d+=1;d<e;d++)a.a[d]=0;a.a[e]&=~sq(0,c)}} +function xq(a,b,c,d){for(var e=!1,f=b>>4,g=c-1>>4;f<=g&&65535==a.a[f];)e=!0,f++;if(f>g)return-1;for(e&&(b=f<<4);b<=c-d;){e=!1;for(f=b+d-1;f>=b;f--)if(a.a[f>>4]>>(f&15)&1){b=f+1;e=!0;break}if(!e)return b}return-1}function yq(a,b,c){if(c<=b)return c;var d=b>>4,e=c-1>>4,f=b&15;b=c-1&15;if(d==e)return f=a.a[d]&sq(f,b),0==f?c:tq(f)+(d<<4);if(f=a.a[d]&sq(f,15))return tq(f)+(d<<4);for(d+=1;d<e;d++)if(f=a.a[d])return tq(f)+(d<<4);a=a.a[e]&sq(0,b);return 0==a?c:tq(a)+(e<<4)};function zq(a,b,c,d){d=d||32;this.l=a;this.c=b;this.B=B(c)?c:0;this.A=d;this.o=Math.ceil(this.l/d);this.u=new qq(this.c);this.j=new qq(this.c*this.o);this.a=null;this.g=-1;this.h=[];this.i=[];this.s=-1;this.m=new Int32Array(b);this.b=null;this.f=-1;this.v=0;this.clear()}function Aq(a,b){var c=a.c;b=c+b;if(a.B&&b>a.B)return!1;rq(a.u,b);rq(a.j,b*a.o);var d=a.m,e=new Int32Array(b);for(e.set(d);c<b;c++)e[c]=-1;a.c=b;a.m=e;return!0} +zq.prototype.clear=function(){uq(this.u);uq(this.j);this.a=null;this.g=-1;this.b=null;this.f=-1;Bq(this);Cq(this);for(var a=0;a<this.c;a++)this.m[a]=-1;this.h=[];this.i=[];this.s=-1};function Dq(a,b,c){b=6*b+5;var d=a.b[b];a.b[b]=c?d|2:d&-3}function Eq(a,b){a.b[6*b+1]=0;a.b[6*b+2]=0;a.b[6*b+3]=0;a.b[6*b+4]=0;a.b[6*b+5]=0;a.b[6*b+0]=a.f;a.f=b}function Bq(a){var b=a.b,c=b?b.length:0,d=c/6,e=d+1024,f=new Int32Array(6*e);if(b)for(var g=0;g<c;g++)f[g]=b[g];a.b=f;for(g=d;g<e;g++)Eq(a,g)} +function Fq(a,b){a.a[6*b+2]=0;a.a[6*b+3]=0;a.a[6*b+4]=0;a.a[6*b+5]=a.l;a.a[6*b+0]=a.g;a.a[6*b+1]=-1;a.g=b}function Gq(a){-1==a.g&&Cq(a);var b=a.g;a.g=a.a[6*a.g+0];a.a[6*b+0]=-1;return b}function Cq(a){var b=a.a,c=b?b.length:0,d=c/6,e=d+128,f=new Int32Array(6*e);if(b)for(var g=0;g<c;g++)f[g]=b[g];a.a=f;for(g=d;g<e;g++)Fq(a,g)}function Hq(a,b,c){var d=a.i[c];B(d)?(a.a[6*b+1]=d,a.a[6*b+0]=-1,a.a[6*d+0]=b):a.h[c]=b;a.i[c]=b} +function Iq(a,b,c){var d=a.a[6*b+1],e=a.a[6*b+0];b==a.h[c]&&(0<=e?a.h[c]=e:delete a.h[c]);b==a.i[c]&&(0<=d?a.i[c]=d:delete a.i[c]);-1!=d&&(a.a[6*d+0]=e);-1!=e&&(a.a[6*e+1]=d);a.a[6*b+1]=-1;a.a[6*b+0]=-1}function Jq(a,b,c){var d=a.a[6*b+2];a.m[d]=-1;wq(a.u,d,d+c);Fq(a,b)} +function Kq(a,b){var c=a.b[6*b+2],d=a.b[6*b+4],e=Math.ceil(a.A/d),f=Math.floor(a.l/e),g=a.m[c];c=c*a.o+a.b[6*b+1]/e;e=a.b[6*b+3]/e;wq(a.j,c,c+e);Eq(a,b);c=a.a[6*g+4];b=c-e;a.a[6*g+4]=b;a.a[6*g+5]=a.l;c==f?(f=a.a[6*g+1],e=a.a[6*g+0],g==a.s&&(a.s=e),-1!=f&&(a.a[6*f+0]=e),-1!=e&&(a.a[6*e+1]=f),a.a[6*g+1]=-1,a.a[6*g+0]=-1,0==b?Jq(a,g,d):Hq(a,g,d)):0==b&&(Iq(a,g,d),Jq(a,g,d))} +function Lq(a,b,c){a:{var d=[b];b=Math.ceil(a.A/c);var e=Math.floor(a.l/b),f=d[0],g=Math.ceil(f/b);if(f>a.l)c=-1;else{var h=-1,k=-1,l=-1,m=-1,n=-1,p=a.h[c];if(B(p))for(;-1!=p;p=a.a[6*p+0])if(m=a.a[6*p+4],!(m+g>e||a.a[6*p+5]<=g))if(h=a.a[6*p+2],k=h*a.o,l=k+e,n=xq(a.j,k,l,g),-1!=n)break;else a.a[6*p+5]=g;if(-1==n){n=xq(a.u,0,a.c,c);-1==n?p=-1:(h=Gq(a),a.a[6*h+2]=n,a.a[6*h+3]=c,vq(a.u,n,n+c),p=a.m[n]=h);if(-1==p){c=-1;break a}Hq(a,p,c);h=a.a[6*p+2];k=h*a.o;l=k+e;m=0;n=k}g=n+g;for(var q=1,t=1;t<d.length;t++){f+= +d[t];var v=n+Math.ceil(f/b);if(v>l)break;if(yq(a.j,g,v)==v)g=v,q++;else break}f=g-n;-1==a.f&&Bq(a);d=a.f;a.f=a.b[6*a.f+0];a.b[6*d+0]=-1;a.b[6*d+1]=(n-k)*b;a.b[6*d+2]=h;a.b[6*d+3]=(g-n)*b;a.b[6*d+4]=c;m+=f;a.a[6*p+4]=m;m==e&&(Iq(a,p,c),c=p,b=a.s,a.a[6*c+1]=-1,a.a[6*c+0]=b,-1!=b&&(a.a[6*b+1]=c),a.s=c);vq(a.j,n,g);c=d}}-1!=c&&a.v++;return c};function Mq(a,b,c,d,e,f,g,h){this.h=a;this.i=!1;this.I=a.i;this.D=h?h.width:1;this.o=h?h.height:1;this.f=new zq(Math.floor(b/this.D),Math.floor(c/this.o),Math.floor(this.I/this.o),h?1:32);this.m=d;this.b=null;this.c=b;this.a=c;this.J=e;this.K=f;this.l=this.g=0;this.v=g||128;this.j={};this.B=this.s=this.C=void 0;this.H=new Uint8Array(64);this.G=[];this.A=this.u=0;this.clear()}F(Mq,Pp);Mq.prototype.X=function(){this.b&&(this.h.deleteTexture(this.b),this.b=null);Mq.R.X.call(this)}; +function Nq(a){this.block=a;this.source=null;this.a=1}function Oq(a){return Math.ceil(a.f.c*a.o/a.v)*a.v}function Pq(a){for(var b in a.j){var c=a.j[b];c.source=null;0<=c.block&&Dq(a.f,c.block,!1)}a.u=0}Mq.prototype.clear=function(){this.f.clear();this.b&&(this.h.deleteTexture(this.b),this.b=null);this.l=this.g=0;this.j={};this.B=this.s=this.C=void 0;this.u=0;this.a=Oq(this);this.b=Qq(this,this.c,this.a);this.A++};function Rq(a){Pq(a);a.b&&a.h.deleteTexture(a.b);a.a=Oq(a);a.b=Qq(a,a.c,a.a);a.A++} +function Sq(a){a.i=!0;a.h=null;a.b=null;Pq(a)}function Tq(a,b){a.i&&(a.i=!1,a.h=b,a.I=b.i,Rq(a))}function Qq(a,b,c){if(a.i)return null;var d=a.h,e=d.createTexture();if(!e||!e.h)return null;d.a.xa(d.a.vb()+1-1,e);d.texParameteri(3553,10240,a.J);d.texParameteri(3553,10241,a.J);d.texParameteri(3553,10242,33071);d.texParameteri(3553,10243,33071);a=a.m;Uo(jq(d,3553),null,b,c,a,5121,0);return e} +function Uq(a){if(6406!=a.m&&!a.i&&0<a.g){var b=a.h,c=a.c,d=a.a,e=a.b,f=Oq(a),g=Qq(a,c,f);if(g){var h=b.createFramebuffer();if(h){var k=Fp(b.b),l=b.a.f;b.bindFramebuffer(36160,h);b.framebufferTexture2D(36160,36064,3553,e,0);b.a.xa(b.a.vb()+1-1,g);b.copyTexSubImage2D(3553,0,0,0,0,0,c,d);b.texSubImage2D(3553,0,0,d,c,f-d,a.m,5121,new Uint8Array(c*(f-d)*4));b.bindFramebuffer(36160,l);b.viewport(k[0],k[1],k[2],k[3]);b.deleteFramebuffer(h);b.deleteTexture(e);a.b=g;a.c=c;a.a=f}else b.deleteTexture(g)}}} +function Vq(a){a.l=0;a.g=0}function Wq(a){if(!a.O()&&!a.i)if(a.g)a.g++;else if(a.b){Oq(a)>a.a&&6408!=a.m&&Rq(a);a.g=1;Oq(a)>a.a&&Uq(a);var b=a.h,c=b.a.vb()+1-1;a.C=Po(b.b);a.s=b.a.c[c];b.a.xa(c,a.b);a.B=yp(b.b,37441);b.pixelStorei(37441,a.K?1:0);for(b=0;b<a.u;b++)c=a.G[b],Xq(a,c.left,c.top,c.width,c.height);a.u=0}} +function Yq(a){if(!a.i&&a.g)if(1<a.g)a.g--;else{var b=a.h;B(a.B)&&(b.pixelStorei(37441,a.B),a.B=void 0);B(a.s)&&(a.s&&a.s.m||b.bindTexture(3553,a.s),a.s=void 0);B(a.C)&&(b.activeTexture(a.C),a.C=void 0);a.g=0}}function Xq(a,b,c,d,e){var f=d*e*4;f>a.H.length&&(a.H=new Uint8Array(f));f=a.m;var g=a.H;Vo(jq(a.h,3553),g,b,c,d,e,f,5121,0)} +function Zq(a,b,c){if(0>=b||b>a.c||0>=c)return-1;b=Math.ceil(b/a.D);c=Math.ceil(c/a.o);var d=Lq(a.f,b,c);if(-1!=d)return d;d=Oq(a)+a.v;if(d>a.I||!Aq(a.f,Math.floor(d/a.o)-a.f.c))return-1;0<a.g&&Oq(a)>a.a&&Uq(a);a=Lq(a.f,b,c);return-1!=a?a:-1} +function $q(a,b,c,d,e,f,g,h,k){if(!(a.i||0>b||!(0<a.g)||0>=g||0>=h||0>e||0>f||e+g>ar(a,b)||f+h>br(a,b))){if(null!==c){var l=a.j[c];if(!l||l.block!=b||d&&l.source&&l.source==d)return}e=cr(a,b)+e;f=dr(a,b)+f;k instanceof Uint8Array?(l=a.m,Vo(jq(a.h,3553),k,e,f,g,h,l,5121,0)):(g=a.m,h=jq(a.h,3553),l=So(h),h.bind(),To(h,k.width,g,5121),h.a.texSubImage2D(l,0,e,f,g,5121,k),h.g.ub(3317));Dq(a.f,b,!0);c&&d&&(a.j[c].source=d)}} +function er(a,b){if(!(0>b)){if(a.f.b[6*b+5]&2)if(0<a.g)Xq(a,cr(a,b),dr(a,b),ar(a,b),br(a,b));else{a.u==a.G.length&&a.G.push(new pq(0,0,0,0));var c=a.G[a.u++];c.left=cr(a,b);c.top=dr(a,b);c.width=ar(a,b);c.height=br(a,b)}a=a.f;Kq(a,b);a.v--}}function fr(a,b){!a.i&&a.b&&(a.l?a.l++:(a.h.a.xa(b,a.b),a.l=1))}function gr(a){!a.i&&a.l&&(1<a.l?a.l--:a.l=0)}function cr(a,b){return a.f.b[6*b+1]*a.D}function dr(a,b){return a.f.b[6*b+2]*a.o}function ar(a,b){return a.f.b[6*b+3]*a.D} +function br(a,b){return a.f.b[6*b+4]*a.o};function hr(a){this.arrayBuffer=new ArrayBuffer(a);this.a=0;new Float32Array(this.arrayBuffer);new Int32Array(this.arrayBuffer);this.g=new Uint32Array(this.arrayBuffer);this.c=new Int16Array(this.arrayBuffer);this.f=new Uint16Array(this.arrayBuffer);new Int8Array(this.arrayBuffer);this.b=new Uint8Array(this.arrayBuffer)};function ir(a,b,c,d){this.a=a;this.f=b;0==c&&(c=1);this.i=c;this.c=d||65536;this.c-=this.c%c;this.j=this.c/c;this.b=new zq(this.j,1,0,4);this.g=[];this.h=[]}function jr(a,b,c){this.a=b;this.buffer=null;this.b=c;this.c=a}function kr(a,b,c,d,e){this.start=a;this.size=b;this.c=b/c;this.b=a/c;this.a=e;this.f=d}function lr(a,b){for(var c=[],d=b,e=a.f*a.c;0<d;){var f=Math.min(d,e);d-=f;c.push(mr(a,f))}a=new jr(b,c,a);B(!1)||(a.buffer=new hr(b));return a} +function mr(a,b){var c=b/a.f/a.i,d=Lq(a.b,c,1);0>d&&(Aq(a.b,1),d=Lq(a.b,c,1));c=a.b.b[6*d+2];var e=a.g[c];if(!e){a.g[c]=e=a.a.createBuffer();a.h[c]=0;var f=a.a.a.b||null;a.a.a.Ua(e);a.a.bufferData(34962,a.f*a.c,35048);a.a.a.Ua(f)}a.h[c]++;return new kr(a.b.b[6*d+1]*a.i*a.f,b,a.f,d,e)} +function nr(a,b,c){c=B(c)?c:b.buffer.b;for(var d=0,e=0;e<b.a.length;++e){var f=b.a[e],g=c.byteLength==f.size?c:new Uint8Array(c.buffer,c.byteOffset+d,f.size),h=a.a.a.b||null;a.a.a.Ua(f.a);a.a.bufferSubData(34962,f.start,g);a.a.a.Ua(h);d+=f.size}b.buffer=null};function or(){this.a=new Int32Array(4096);this.b=-1;this.c={};for(var a=4095;0<=a;a--)this.a[a]=-1-this.b,this.b=a;this.g=this.f=null}function pr(a,b){var c=a.c[b];if(B(c))a.a[c]++;else{if(0>a.b){var d=2*a.a.length;c=new Int32Array(d);c.set(a.a);for(--d;d>=a.a.length;d--)c[d]=-1-a.b,a.b=d;a.a=c}c=a.b;a.b=-1-a.a[c];a.a[c]=1;a.c[b]=c}return c}function qr(a,b){a=a.c[b];return B(a)?a:-1};var rr=function(a){return function(){return a}}(!1);function sr(a){return a};function tr(a){x.setTimeout(function(){throw a;},0)}function ur(a,b,c){var d=a;b&&(d=D(a,b));d=vr(d);!ya(x.setImmediate)||!c&&x.Window&&x.Window.prototype&&!fb("Edge")&&x.Window.prototype.setImmediate==x.setImmediate?(wr||(wr=xr()),wr(d)):x.setImmediate(d)}var wr; +function xr(){var a=x.MessageChannel;"undefined"===typeof a&&"undefined"!==typeof window&&window.postMessage&&window.addEventListener&&!fb("Presto")&&(a=function(){var a=document.createElement("IFRAME");a.style.display="none";a.src="";document.documentElement.appendChild(a);var b=a.contentWindow;a=b.document;a.open();a.write("");a.close();var c="callImmediate"+Math.random(),d="file:"==b.location.protocol?"*":b.location.protocol+"//"+b.location.host;a=D(function(a){if(("*"==d||a.origin==d)&&a.data== +c)this.port1.onmessage()},this);b.addEventListener("message",a,!1);this.port1={};this.port2={postMessage:function(){b.postMessage(c,d)}}});if("undefined"!==typeof a&&!fb("Trident")&&!fb("MSIE")){var b=new a,c={},d=c;b.port1.onmessage=function(){if(B(c.next)){c=c.next;var a=c.be;c.be=null;a()}};return function(a){d.next={be:a};d=d.next;b.port2.postMessage(0)}}return"undefined"!==typeof document&&"onreadystatechange"in document.createElement("SCRIPT")?function(a){var b=document.createElement("SCRIPT"); +b.onreadystatechange=function(){b.onreadystatechange=null;b.parentNode.removeChild(b);b=null;a();a=null};document.documentElement.appendChild(b)}:function(a){x.setTimeout(a,0)}}var vr=sr;Hb(function(a){vr=a});function yr(){this.m=sa;this.f=this.g=!1;this.h=null;this.s=x.requestAnimationFrame||x.webkitRequestAnimationFrame||x.mozRequestAnimationFrame||x.oRequestAnimationFrame||x.msRequestAnimationFrame||function(a){x.setTimeout(a,16)};var a=this;this.j=function(){a.a=!1;zr(a)};this.l=function(){a.c=!1;a.g=!1;zr(a)};this.c=this.a=!1;this.b=!0;this.i=0;lo(D(this.o,this),void 0,void 0)}function zr(a){a.f=!0;try{a.h.xb()}catch(b){throw a.m(b),b;}a.g&&(a.a&&a.b||Ar(a));a.f=!1} +function Br(a){a.b?a.a||a.c||(a.s.call(x,a.j),a.a=!0):Ar(a)}function Cr(a){zc?Br(a):a.f?a.g=!0:a.b&&a.a||Ar(a)}function Ar(a){a.c||!a.b&&E()>a.i||(ur(a.l),a.c=!0)}yr.prototype.o=function(a){(this.b=a)&&!this.a?Ar(this):this.i=E()+1E4};function Dr(){};var Er=[];function Fr(a,b,c){this.b=a||new yr;this.b.h=this;E();this.m=Gr;this.D=this.s=this.c=0;this.l=this.i=!1;this.g=[];this.f=[];this.h=[];this.a=[];this.a[0]=[];this.a[1]=[];this.a[2]=[];this.a[3]=[];this.a[4]=[];this.a[5]=[];this.A=[];this.G=!!b;this.B=!c;this.o=!1;this.u=this.v=0;Er.push(this)}var Gr=1E3/60,Hr=1E4/60;r=Fr.prototype;r.Te=function(a){this.g.push(a);Br(this.b)};r.Pd=function(a){this.f.push(a);Br(this.b)};r.Ue=function(a){this.h.push(a);Br(this.b)};r.Mb=function(a,b){Ir(this,a,Jr(b,!1))}; +r.ed=function(a,b){Ir(this,a,Jr(b,!0))};function Jr(a,b){a*=2;b&&(a+=1);return a}function Ir(a,b,c){var d=b.__maps_realtime_JobScheduler_next_step;d&&d!=Dr||(b.__maps_realtime_JobScheduler_next_step=b.start,b.__maps_realtime_JobScheduler_priority=c,a.a[c].push(b),a.i||Cr(a.b))}r.Pe=function(a){a.__maps_realtime_JobScheduler_next_step=null}; +r.qd=function(a,b){var c=a.__maps_realtime_JobScheduler_next_step;if(c&&c!=Dr&&(c=a.__maps_realtime_JobScheduler_priority,b=1==c||3==c||5==c?Jr(b,!0):Jr(b,!1),c!=b)){for(var d=this.a[c].length,e=0;e<d;++e)if(this.a[c][e]==a){this.a[c][e]=null;break}a.__maps_realtime_JobScheduler_priority=b;this.a[b].push(a)}}; +r.zc=function(){try{this.i=!0;for(var a=E()+2,b=5;0<=b&&Kr(this,b,a);b--);}finally{this.i=!1,(0<this.a[5].length||0<this.a[4].length||0<this.a[3].length||0<this.a[2].length||0<this.a[1].length||0<this.a[0].length)&&Cr(this.b)}}; +r.xb=function(){var a=E();this.i=!0;var b=0,c=this.A;if(0<c.length){for(b=0;b<c.length;b++)this.Mb(c[b].Df,c[b].priority);this.A=[]}try{E();var d=this.g;this.g=[];var e=d.length;for(c=0;c<e;c++){var f=d[c];Lr();Mr(f)}E();if(this.G){Nr(this);Or(this,a);var g=Infinity}else if(this.B)if(a-this.s<this.m-(6+this.c))g=a+this.m-3;else{Nr(this);Or(this,a);var h=E();d=h-a;this.c*=.97;this.c+=.03*d;var k=Math.ceil(1/Gr*(this.c+3+6))*Gr;k=k<Gr?Gr:k;this.m=k=k>Hr?Hr:k;g=Pr(this,a,h)}else{Nr(this);Or(this,a); +var l=E();g=Pr(this,a,l)}this.l=!1;for(b=5;0<=b&&Kr(this,b,g);b--);}finally{this.i=!1,b=0<this.h.length||0<this.f.length||0<this.g.length,g=0<this.a[5].length||0<this.a[4].length||0<this.a[3].length||0<this.a[2].length||0<this.a[1].length||0<this.a[0].length,b?Br(this.b):g&&Cr(this.b),this.o&&(this.u+=E()-a),this.o=g||b}};function Nr(a){E();var b=a.f;a.f=[];a=b.length;for(var c=0;c<a;c++){var d=b[c];Lr();Qr(d)}E()}function Pr(a,b,c){a=b+a.m-3;c-=a;0<c&&(a+=Math.ceil(c/Gr)*Gr);return a} +Hb(function(a){Fr.prototype.xb=a(Fr.prototype.xb)}); +function Kr(a,b,c){E();if(a.l&&E()>=c)return!1;var d=a.a[b];if(0==d.length)return!0;for(var e=[],f=!1,g=0;g<d.length&&!f;g++){var h=d[g];if(h)for(;;){var k=h.__maps_realtime_JobScheduler_next_step;if(!k||k==Dr)break;k=E();if(a.l&&k>=c){f=!0;e.push(g);break}Lr();k=Dr;try{k=h.__maps_realtime_JobScheduler_next_step()}finally{h.__maps_realtime_JobScheduler_next_step=k,a.l=!0}if(k==Dr)break}}E();k=[];for(var l=0;l<e.length;l++)if(h=d[e[l]]){var m=h.__maps_realtime_JobScheduler_next_step;m&&m!=Dr&&k.push(h)}if(f)return a.a[b]= +k.concat(d.slice(g-1)),!1;a.a[b]=k;return E()<c}function Or(a,b){E();var c=b-a.s;a.o&&(a.D++,a.v+=c,a.u=0);a.s=b;b=a.h;a.h=[];a=b.length;for(c=0;c<a;c++){var d=b[c];Lr();vo(d)}E()}Fr.prototype.C=function(){if(0<this.h.length||0<this.f.length||0<this.g.length)return!0;if(!B(void 0))return!1;for(var a=Jr(void 0,!1);5>=a;a++)if(this.a[a].length)return!0;return!1};function Lr(){x.performance&&x.performance.now||E()}Fr.prototype.j=function(){return sa};function Rr(a){this.byteLength=a;this.a=Array(a);for(var b=0;b<a;b++)this.a[b]=0}function Sr(){}function Tr(a,b,c){if(a instanceof Rr)for(this.length=c||a.byteLength/this.a,this.buffer=new Rr(a.byteLength),b=0;b<this.length;b++)this[b]=a.a[b];else{if(xa(a)){for(b=0;b<a.length;b++)this[b]=a[b];this.length=a.length}else for(this.length=a||0,b=0;b<this.length;b++)this[b]=0;this.buffer=new Rr(this.length*this.a)}this.buffer.a=this;this.byteLength=this.length*this.a}F(Tr,Sr); +Tr.prototype.set=function(a,b){b=b||0;for(var c=0;c<a.length;c++)this[b+c]=a[c]};Tr.prototype.slice=function(){};Tr.prototype.subarray=function(){return null};function Ur(a,b,c){Tr.call(this,a,b,c)}F(Ur,Tr);Ur.prototype.a=1;function Vr(a,b,c){Tr.call(this,a,b,c)}F(Vr,Tr);Vr.prototype.a=1;function Wr(a,b,c){Tr.call(this,a,b,c)}F(Wr,Tr);Wr.prototype.a=2;function Xr(a,b,c){Tr.call(this,a,b,c)}F(Xr,Tr);Xr.prototype.a=2;function Yr(a,b,c){Tr.call(this,a,b,c)}F(Yr,Tr);Yr.prototype.a=4; +function Zr(a,b,c){Tr.call(this,a,b,c)}F(Zr,Tr);Zr.prototype.a=4;function $r(a,b,c){Tr.call(this,a,b,c)}F($r,Tr);$r.prototype.a=4;function as(a,b,c){Tr.call(this,a,b,c)}F(as,Tr);as.prototype.a=4;function bs(){}F(bs,Sr);"undefined"==typeof ArrayBuffer&&(x.ArrayBuffer=Rr);"undefined"==typeof Int8Array&&(x.Int8Array=Ur);"undefined"==typeof Uint8Array&&(x.Uint8Array=Vr);"undefined"==typeof Int16Array&&(x.Int16Array=Wr);"undefined"==typeof Uint16Array&&(x.Uint16Array=Xr); +"undefined"==typeof Int32Array&&(x.Int32Array=Yr);"undefined"==typeof Uint32Array&&(x.Uint32Array=Zr);"undefined"==typeof Float32Array&&(x.Float32Array=$r);"undefined"==typeof Float64Array&&(x.Float64Array=as);"undefined"==typeof DataView&&(x.DataView=bs);function cs(a,b){var c=this;a?this.canvas=a:(this.canvas={},this.canvas.attachEvent=function(){},this.canvas.width=0,this.canvas.height=0,this.canvas.getBoundingClientRect=function(){return{left:0,right:c.canvas.width,top:0,bottom:c.canvas.height,width:c.canvas.width,height:c.canvas.height}});this.C=new ds;if(b)for(var d in b){if(!(d in this.C))throw Error("Invalid context attribute: "+d);this.C[d]=b[d]}this.m=[];this.o=[];this.c=0;this.g=[0,0,0,0];this.A={};this.A.ANGLE_instanced_arrays={VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE:1, +drawArraysInstancedANGLE:function(){},drawElementsInstancedANGLE:function(){},vertexAttribDivisorANGLE:function(){}};this.u=this.s=this.f=this.b=null;this.h=[0,0,0,0];this.i=[!0,!0,!0,!0];this.l=new pq(0,0,0,0);this.j=new pq(0,0,0,0);this.B={};this.v=[0,1];Object.defineProperty(this,"drawingBufferWidth",{get:function(){return c.canvas.width}});Object.defineProperty(this,"drawingBufferHeight",{get:function(){return c.canvas.height}});this.a=[];this.a[34016]=33984;this.a[33902]=[1,10];this.a[33901]= +[1,63];this.a[3413]=8;this.a[3042]=!1;this.a[32773]=this.g;this.a[32970]=0;this.a[32968]=0;this.a[34877]=32774;this.a[32777]=32774;this.a[32971]=1;this.a[32969]=1;this.a[3412]=8;this.a[3106]=this.h;this.a[3107]=this.i;this.a[34467]=[];this.a[2884]=!1;this.a[2885]=1029;this.a[35725]=null;this.a[3414]=24;this.a[2931]=1;this.a[2932]=513;this.a[2928]=this.v;this.a[2929]=!1;this.a[2930]=!0;this.a[3024]=!0;this.a[2886]=2305;this.a[33170]=4352;this.a[3411]=8;this.a[2849]=1;this.a[35661]=96;this.a[34076]= +8192;this.a[36349]=512;this.a[34024]=8192;this.a[34930]=32;this.a[3379]=8192;this.a[36348]=15;this.a[34921]=16;this.a[35660]=32;this.a[36347]=1024;this.a[3386]=[8192,8192];this.a[3333]=4;this.a[32824]=0;this.a[32823]=!1;this.a[10752]=0;this.a[3410]=8;this.a[7937]="Fake WebGL";this.a[32937]=4;this.a[32936]=1;this.a[32939]=!1;this.a[32938]=1;this.a[3088]=this.j;this.a[3089]=!1;this.a[35724]="WebGL GLSL ES 1.0 (OpenGL ES GLSL ES 1.0 TotallyFake)";this.a[34817]=7680;this.a[34816]=519;this.a[34818]=7680; +this.a[34819]=7680;this.a[36003]=0;this.a[36004]=4294967295;this.a[36005]=4294967295;this.a[3415]=8;this.a[2961]=0;this.a[2964]=7680;this.a[2962]=519;this.a[2965]=7680;this.a[2966]=7680;this.a[2967]=0;this.a[2960]=!1;this.a[2963]=4294967295;this.a[2968]=4294967295;this.a[3408]=8;this.a[3317]=4;this.a[37443]=37444;this.a[37440]=!1;this.a[37441]=!1;this.a[7936]="Fakers";this.a[7938]="WebGL 1.0 (OpenGL ES 2.0 TotallyFake)";this.a[2978]=this.l;this.D=[];for(a=0;a<this.a[35661];++a)this.m[a]=null,this.o[a]= +null;es()}r=cs.prototype;r.createProgram=function(){return new fs};r.deleteProgram=function(a){a.a=!0};r.createShader=function(a){return new gs(a)};r.deleteShader=function(a){a.a=!0};r.shaderSource=function(a,b){a.source=b};r.compileShader=function(a){a.b=!0};r.attachShader=function(a,b){35633==b.type?a.c=b:35632==b.type&&(a.b=b)};r.detachShader=function(a,b){35633==b.type?a.c=null:35632==b.type&&(a.b=null)}; +r.linkProgram=function(a){function b(a){switch(a){case "bool":return 35670;case "bvec2":return 35671;case "bvec3":return 35672;case "bvec4":return 35673;case "int":return 5124;case "ivec2":return 35667;case "ivec3":return 35668;case "ivec4":return 35669;case "float":return 5126;case "vec2":return 35664;case "vec3":return 35665;case "vec4":return 35666;case "mat2":return 35674;case "mat3":return 35675;case "mat4":return 35676;case "sampler2D":return 35678;case "samplerCube":return 35680}}if(a.c&&a.c.b&& +a.b&&a.b.b){var c=a.c.source+a.b.source;c=c.replace(/\n/g," ");for(var d=/uniform (\w+) (.*?);/g,e,f=[],g=[];e=d.exec(c);){var h=e[1],k=e[2].split(",");for(e=0;e<k.length;e++)-1==f.indexOf(k[e].trim())&&(f.push(k[e].trim()),g.push(b(h)))}for(e=0;e<f.length;e++)c=new hs,c.name=f[e],c.type=g[e],d=new is,d.name=f[e],d.index=e,a.i.push(f[e]),a.f.push(c),a.h.push(d);a.g=!0}};r.getError=function(){return 0}; +r.getProgramParameter=function(a,b){switch(b){case 35712:return a.a;case 35714:return a.g;case 35715:return!0;case 35717:return!!a.c+!!a.b;case 35721:return 0;case 35718:return a.f.length}};r.getActiveUniform=function(a,b){return a.f[b]};r.getUniformLocation=function(a,b){return a.h[a.i.indexOf(b)]};r.useProgram=function(){};r.createTexture=function(){return new js};r.deleteTexture=function(){};r.createFramebuffer=function(){return new ks};r.deleteFramebuffer=function(a){a.a=!0}; +r.createRenderbuffer=function(){return new ls};r.deleteRenderbuffer=function(a){a.a=!0};r.createBuffer=function(){return new ms};r.deleteBuffer=function(a){a.a=!0};r.viewport=function(a,b,c,d){this.l.left=a;this.l.top=b;this.l.width=c;this.l.height=d};r.scissor=function(a,b,c,d){this.j.left=a;this.j.top=b;this.j.width=c;this.j.height=d};r.activeTexture=function(a){this.c=a-33984;this.a[34016]=a};r.bindFramebuffer=function(a,b){this.b=b};r.bindRenderbuffer=function(a,b){this.f=b}; +r.bindTexture=function(a,b){3553==a?this.m[this.c]=b:this.o[this.c]=b};function ns(a,b){return 3553==b?a.m[a.c]:a.o[a.c]}r.compressedTexImage2D=function(a,b,c,d,e,f,g){a=ns(this,a);a.format=c;a.width=d;a.height=e;a.data=g};r.copyTexImage2D=function(a,b,c,d,e,f,g){a=ns(this,a);a.format=c;a.width=f;a.height=g;a.data=this.b?this.b.getData()+" from ("+d+", "+e+") with size of "+f+"x"+g:"Screen from ("+d+", "+e+") with size of "+f+"x"+g}; +r.framebufferTexture2D=function(a,b,c,d){switch(b){case 36064:this.b.b=d;break;case 36096:this.b.c=d;break;case 36128:this.b.f=d}};r.framebufferRenderbuffer=function(a,b,c,d){switch(b){case 36064:this.b.b=d;break;case 36096:this.b.c=d;break;case 36128:this.b.f=d;break;case 33306:this.b.g=d}};r.renderbufferStorage=function(a,b,c,d){this.f.format=b;this.f.width=c;this.f.height=d;this.f.data="Empty "+c+"x"+d+" renderbuffer"}; +r.texImage2D=function(a){arguments.length==this.df.length&&this.df.apply(this,arguments);arguments.length==this.cf.length&&this.cf.apply(this,arguments)};r.texSubImage2D=function(){};r.copyTexSubImage2D=function(){};r.df=function(a,b,c,d,e,f){a=ns(this,a);a.format=c;a.width=f.width;a.height=f.height;a.data="Empty "+f.width+"x"+f.height+"texture"};r.cf=function(a,b,c,d,e,f,g,h,k){a=ns(this,a);a.format=c;a.width=d;a.height=e;k?a.data=k:a.data="Empty "+d+"x"+e+"texture"};r.uniform1f=function(){}; +r.uniform1i=function(){};r.uniform2f=function(){};r.uniform4f=function(){};r.uniform2fv=function(){};r.uniform3fv=function(){};r.uniform4fv=function(){};r.uniformMatrix4fv=function(){};r.texParameteri=function(){};r.enable=function(a){this.B[a]=!0};r.disable=function(a){this.B[a]=!1};r.bindBuffer=function(a,b){switch(a){case 34962:this.s=b;break;case 34963:this.u=b;break;default:throw Error("Invalid bindBuffer target.");}}; +r.bufferData=function(a,b){switch(a){case 34962:this.s.arrayBuffer=b;break;case 34963:this.u.arrayBuffer=b;break;default:throw Error("Invalid bindBuffer target.");}};r.bufferSubData=function(){};r.drawArrays=function(){};r.getParameter=function(a){if(34964==a)return this.s;if(34965==a)return this.u;if(36006==a)return this.b;if(36007==a)return this.f;if(32873==a)return this.m[this.c];if(34068==a)return this.o[this.c];a=this.a[a];return a instanceof pq?[a.left,a.top,a.width,a.height]:a}; +r.vertexAttribPointer=function(){};r.blendColor=function(a,b,c,d){this.g[0]=a;this.g[1]=b;this.g[2]=c;this.g[3]=d};r.blendEquation=function(a){this.a[32777]=a;this.a[34877]=a};r.blendEquationSeparate=function(a,b){this.a[32777]=a;this.a[34877]=b};r.blendFunc=function(a,b){this.a[32969]=a;this.a[32968]=b;this.a[32971]=a;this.a[32970]=b};r.blendFuncSeparate=function(a,b,c,d){this.a[32969]=a;this.a[32968]=b;this.a[32971]=c;this.a[32970]=d};r.depthFunc=function(a){this.a[2932]=a}; +r.sampleCoverage=function(a,b){this.a[32938]=a;this.a[32939]=b};r.stencilFunc=function(a,b,c){this.a[2962]=a;this.a[2967]=b;this.a[2963]=c;this.a[34816]=a;this.a[36003]=b;this.a[36004]=c};r.stencilOp=function(a,b,c){this.a[2964]=a;this.a[2965]=b;this.a[2966]=c;this.a[34817]=a;this.a[34818]=b;this.a[34819]=c};r.clearColor=function(a,b,c,d){this.h[0]=a;this.h[1]=b;this.h[2]=c;this.h[3]=d};r.clearDepth=function(a){this.a[2931]=a};r.clearStencil=function(a){this.a[2961]=a}; +r.colorMask=function(a,b,c,d){this.i[0]=a;this.i[1]=b;this.i[2]=c;this.i[3]=d};r.depthMask=function(a){this.a[2930]=a};r.depthRange=function(a,b){this.v[0]=a;this.v[1]=b};r.cullFace=function(a){this.a[2885]=a};r.frontFace=function(a){this.a[2886]=a};r.lineWidth=function(a){this.a[2849]=a};r.polygonOffset=function(a,b){this.a[32824]=a;this.a[10752]=b};r.enableVertexAttribArray=function(a){this.D[a]=!0};r.disableVertexAttribArray=function(a){this.D[a]=!1};r.pixelStorei=function(a,b){this.a[a]=b}; +r.hint=function(a,b){this.a[a]=b};r.isContextLost=function(){return!1};r.clear=function(){};r.getAttribLocation=function(){return 0};r.bindAttribLocation=function(){};r.getSupportedExtensions=function(){return Object.keys(this.A)};r.getExtension=function(a){return this.A[a]||null};r.getShaderPrecisionFormat=function(){return{rangeMin:-64,rangeMax:64,precision:64}};r.readPixels=function(){}; +function ds(){this.depth=this.alpha=!0;this.stencil=!1;this.premultipliedAlpha=this.antialias=!0;this.failIfMajorPerformanceCaveat=this.preferLowPowerToHighPerformance=this.preserveDrawingBuffer=!1}function js(){this.format=null;this.height=this.width=0;this.data="None"}function fs(){this.b=this.c=null;this.a=this.g=!1;this.i=[];this.f=[];this.h=[]}function gs(a){this.type=a;this.source=null;this.a=this.b=!1}function ks(){this.g=this.f=this.c=this.b=null;this.a=!1} +function ms(){this.arrayBuffer=null;this.a=!1}ks.prototype.getData=function(){return this.b.data};function ls(){this.height=this.width=0;this.format=null;this.data="None";this.a=!1}function hs(){this.name="";this.type=-1}function is(){this.name="";this.index=-1}function os(a){this.a=a}function es(){x.WebGLActiveInfo=hs;x.WebGLBuffer=ms;x.WebGLTexture=js;x.WebGLRenderbuffer=ls;x.WebGLFramebuffer=ks;x.WebGLUniformLocation=is;x.WebGLContextEvent=os};function ps(){}var qs=new ps;ps.prototype.b=function(a,b){var c=Array(rs(a,b));ss(a,b,c,0);return c.join("")};var ts=/^([0-9]+)([a-zB])([\s\S]*)/,us=/(\*)/g,vs=/(!)/g,ws=/(\*2A)/gi,xs=/(\*21)/gi;function rs(a,b){var c=0,d;for(d in b.F){var e=parseInt(d,10),f=b.F[e];e=a[e+b.a];if(f&&null!=e)if(3==f.label)for(var g=0;g<e.length;++g)c+=ys(e[g],f);else c+=ys(e,f)}return c}function ys(a,b){var c=4;"m"==b.type&&(c+=rs(a,b.N));return c} +function ss(a,b,c,d){for(var e in b.F){var f=parseInt(e,10),g=b.F[f],h=a[f+b.a];if(g&&null!=h)if(3==g.label)for(var k=0;k<h.length;++k)d=zs(h[k],f,g,c,d);else d=zs(h,f,g,c,d)}return d} +function zs(a,b,c,d,e){d[e++]="!";d[e++]=""+b;if("m"==c.type)d[e++]=c.type,d[e++]="",b=e,e=ss(a,c.N,d,e),d[b-1]=""+(e-b>>2);else{c=c.type;if("b"==c)a=a?"1":"0";else if("i"==c||"j"==c||"u"==c||"v"==c||"n"==c||"o"==c){if(!pa(a)||"j"!=c&&"v"!=c&&"o"!=c)a=""+Math.floor(a)}else if("B"==c)a=pa(a)?Qd(a):xa(a)?Dc(a,!0):""+a,a=Rd(a);else if(a=""+a,"s"==c){var f=a;b=encodeURIComponent(f).replace(/%20/g,"+");var g=b.match(/%[89AB]/ig);f=f.length+(g?g.length:0);if(4*Math.ceil(f/3)-(3-f%3)%3<b.length){c=[];for(f= +b=0;f<a.length;f++)g=a.charCodeAt(f),128>g?c[b++]=g:(2048>g?c[b++]=g>>6|192:(55296==(g&64512)&&f+1<a.length&&56320==(a.charCodeAt(f+1)&64512)?(g=65536+((g&1023)<<10)+(a.charCodeAt(++f)&1023),c[b++]=g>>18|240,c[b++]=g>>12&63|128):c[b++]=g>>12|224,c[b++]=g>>6&63|128),c[b++]=g&63|128);a=Dc(c,!0);a=Rd(a);c="z"}else-1!=a.indexOf("*")&&(a=a.replace(us,"*2A")),-1!=a.indexOf("!")&&(a=a.replace(vs,"*21"))}d[e++]=c;d[e++]=a}return e}function As(a){return-1!=a.indexOf("*21")?a.replace(xs,"!"):a} +function Bs(a){var b=a.charCodeAt(0).toString(16),c=new RegExp("(\\*"+b+")","gi");b="*"+b;var d=b.toLowerCase();return function(e){return-1!=e.indexOf(b)||-1!=e.indexOf(d)?e.replace(c,a):e}}ps.prototype.a=function(a,b,c){var d=As,e="!",f=a[0];if("0">f||"9"<f)a=a.substr(1),f!=e&&(e=f,d=Bs(e));a=a.split(e);b.length=0;return Cs(0,a.length,a,d,c,b)}; +function Cs(a,b,c,d,e,f){if(a+b>c.length)return!1;var g=a;for(a+=b;g<a;++g){var h=ts.exec(c[g]);if(!h)return!1;b=parseInt(h[1],10);var k=h[2],l=h[3];l=d(l);if(-1!=l.indexOf("*2A")||-1!=l.indexOf("*2a"))l=l.replace(ws,"*");var m=0;if("m"==k&&(m=parseInt(l,10),isNaN(m)))return!1;var n=e.F[b];if(n){h=h[2];if("z"==h){h="s";l=Fc(l);k=[];for(var p=0,q=0;p<l.length;){var t=l[p++];if(128>t)k[q++]=String.fromCharCode(t);else if(191<t&&224>t){var v=l[p++];k[q++]=String.fromCharCode((t&31)<<6|v&63)}else if(239< +t&&365>t){v=l[p++];var u=l[p++],w=l[p++];t=((t&7)<<18|(v&63)<<12|(u&63)<<6|w&63)-65536;k[q++]=String.fromCharCode(55296+(t>>10));k[q++]=String.fromCharCode(56320+(t&1023))}else v=l[p++],u=l[p++],k[q++]=String.fromCharCode((t&15)<<12|(v&63)<<6|u&63)}l=k.join("")}if(n.type!=h)return!1;if("m"==n.type){n=n.N;l=[];if(!Cs(g+1,m,c,d,n,l))return!1;g+=m}a:{m=l;h=b;l=e;b=f;n=l.F[h];if("B"==n.type)m=Sd(String(m));else if("s"!=n.type&&"m"!=n.type&&!pa(n.tf)){k="f"!=n.type&&"d"!=n.type?parseInt(m,10):parseFloat(m); +if(isNaN(k)){b=!1;break a}"b"==n.type?m=0!=k:m=k}h+=l.a||0;3==n.label?Nd(b,h).push(m):b[h]=m;b=!0}if(!b)return!1}else"m"==k&&(g+=m)}return!0};function Ds(a){var b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_."[ye(a,0,0)&63];b=b+":"+a.wa();for(var c=0;c<Fe(a,3);++c)b+=":",b+=ze(new Qn(Ee(a,3,c)),0),b+=":",b+=(new Qn(Ee(a,3,c))).na();xe(a,7)&&(b+=":tkn:",a=new Bn(a.data[7]),c=Nn(),a=te.b(a.data,c),b+=a);return b};function Es(a){this.a=a?a.slice():[];this.b=Array(this.a.length)}function Fs(a,b,c){for(var d=Array(a.a.length),e=0;e<a.a.length;++e){var f=a.a[e],g=a.b[e];g||(g=a.b[e]=Ds(f));var h=null;c&&(h=(g=c.a[g])?g.a.h(b):null);h||(h=xe(f,2)?X(f,2):null);d[e]=h}return d} +function Gs(a,b){if(a==b)return!0;if(ye(a,0,0)!=ye(b,0,0)||a.wa()!=b.wa()||xe(a,7)!=xe(b,7))return!1;var c=Fe(a,3);if(c!=Fe(b,3))return!1;for(var d=0;d<c;++d){var e=new Qn(Ee(a,3,d)),f=new Qn(Ee(b,3,d));if(ze(e,0)!=ze(f,0)||e.na()!=f.na())return!1}return xe(a,7)&&!Ge(new Bn(a.data[7]),new Bn(b.data[7]))?!1:!0}var Hs=new On;Hs.data[1]="m";Hs.data[0]=0;var Is=new Es([Hs]);function Js(a){this.a=a?a.slice():[]}function Ks(a,b){if(a.a.length!=b.a.length)return!1;for(var c=0;c<a.a.length;++c)if(!Ge(a.a[c],b.a[c]))return!1;return!0}function Ls(a){if(1==a.a.length&&(a=a.a[0],68==ye(a,0,37)))for(var b=Fe(a,1),c=0;c<b;c++){var d=new Un(Ee(a,1,c));if("set"==ze(d,0))return d.na()}return null} +function Ms(a){for(var b="",c=0;c<a.a.length;++c){0<c&&(b+=",");var d=a.a[c];b+=ye(d,0,37);for(var e=0;e<Fe(d,1);++e)b+=":",b+=ze(new Un(Ee(d,1,e)),0),b+=":",b+=(new Un(Ee(d,1,e))).na()}return b}var Ns=new Js;function Os(a,b,c,d,e,f){this.c=a||Ns;this.a=b||Is;this.h=c||"";this.g=d||"";this.f=e||null;this.b=f||null;this.i=""}function Ps(a,b){var c;if(!(c=a==b)){if(c=Ks(a.c,b.c))a:{c=a.a;var d=b.a;if(d&&c.a.length==d.a.length){for(var e=0;e<c.a.length;++e)if(!Ge(c.a[e],d.a[e])){c=!1;break a}c=!0}else c=!1}c=c&&a.h==b.h&&a.g==b.g&&a.f==b.f&&(a.b?!!b.b&&Ps(a.b,b.b):!b.b)}return c} +function Qs(a){if(!a.i){for(var b=a.a,c="",d=0;d<b.a.length;++d){0<d&&(c+=",");var e=b.b[d];e||(e=b.b[d]=Ds(b.a[d]));c+=e}a.i=c+":"+Ms(a.c)+":"+a.h+":"+a.g}return a.i}var Rs=new Os(void 0,new Es);function Ss(){this.a={};this.c=!1}function Ts(a,b){return(a=a.a[b])&&a.loaded?a.bb:null}function Us(a,b,c){var d=a.a[b];if(d)d.loaded?c(!0,d.bb):d.pd.push(c);else{var e=go("IMG");0!=b.indexOf("data:")&&(e.crossOrigin=a.c?"use-credentials":"");d=a.a[b]={bb:e,loaded:!1,pd:[c]};d.Kf=ec(e,"load",D(a.b,a,d,b,!0));d.Jf=ec(e,"error",D(a.b,a,d,b,!1));e.src=b}}function Vs(a,b){a.c=b} +Ss.prototype.b=function(a,b,c){mc(c?a.Jf:a.Kf);(a.loaded=c)||this.a[b]===a&&delete this.a[b];b=a.pd;for(var d=0;d<b.length;++d)b[d](c,a.bb);a.pd.length=0};ta(Ss);function Ws(a,b){this.a=a;this.b=b;this.c=0==a.indexOf("data:")}function Xs(a,b,c){if(!a.a)return"";var d=a.a;if(a.c)return d;null===a.b&&(a=-1!=d.indexOf("?"),d+=(a?"&scale=":"?scale=")+b);c&&(a=-1!=d.indexOf("?"),d+=(a?"&text=":"?text=")+encodeURIComponent(String(c)));return d}function Ys(a,b,c){return a.a?(a=Xs(a,b,c),Ts(Ss.sc(),a)):null} +function Zs(a,b,c,d,e){if((a=Ys(a,d,e))&&(a.width!=b||a.height!=c)){d=go("CANVAS");d.width=b;d.height=c;e=d.getContext("2d");try{return e.drawImage(a,0,0,b,c),d}catch(f){}}return a}function $s(a,b,c){var d=new pq(0,0,0,0);if(a=Ys(a,b,c))d.width=a.width,d.height=a.height;return d}function at(a,b,c){a=$s(a,b,c);a.width/=b;a.height/=b;a.left=-a.width/2;a.top=-a.height/2;return a};function bt(){this.a=this.b=null}bt.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}null!==this.a&&(b=this.a,a[1]=b);return a};bt.prototype.getExtension=function(){return null};function ct(a,b){for(;G(b);)switch(b.a){case 1:var c=N(b);a.b=c;break;case 2:c=L(b);a.a=c;break;default:H(b)}}bt.prototype.wa=function(){return null==this.a?"":this.a};function dt(){this.b=this.a=null}function et(){this.a=null}dt.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[0]=b}null!==this.b&&(b=this.b,a[1]=b);return a};dt.prototype.getExtension=function(){return null};function ft(){return new dt}function gt(a){if(null===a)a=null;else{var b=new dt;if(b.a)for(var c=0;c<b.a.length;c++){var d=b.a[c];d&&ht(d)}b.a=null;b.b=null;b.a=Bd(a.a,it);b.b=a.b;a=b}return a}function jt(){} +function kt(a,b){for(;G(b);)switch(b.a){case 1:var c=new et;O(b,c,lt);a.a=a.a||[];a.a.push(c);break;case 2:c=L(b);a.b=c;break;default:H(b)}}function mt(a,b){return a===b?!0:null===a||null===b?!1:Dd(a.a,b.a,nt)&&a.b===b.b?!0:!1}et.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.w();a[2]=b}return a};function ht(a){var b=a.a;b&&(b.b=null,b.a=null);a.a=null}et.prototype.getExtension=function(){return null}; +function it(a){if(null===a)var b=null;else{b=new et;ht(b);if(a.a){var c=new bt;a=a.a;c.b=null;c.a=null;c.b=a.b;c.a=a.a}else c=null;b.a=c}return b}function lt(a,b){for(;G(b);)switch(b.a){case 3:var c=new bt;O(b,c,ct);a.a=c;break;default:H(b)}}function nt(a,b){a===b?b=!0:null===a||null===b?b=!1:(a=a.a,b=b.a,b=a===b||(null===a||null===b?0:a.b===b.b&&a.a===b.a)?!0:!1);return b};function ot(){this.c=this.h=this.b=this.i=this.g=this.a=this.f=null}function pt(){this.h=this.c=this.f=this.i=this.g=this.a=this.b=null}function qt(){this.a=this.b=null}function rt(){this.b=this.a=null}function st(){this.c=this.a=this.f=this.b=null}function tt(){this.a=null} +ot.prototype.w=function(){var a=[];if(null!==this.f){var b=this.f;a[0]=b}if(null!==this.a){b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[1]=b}null!==this.g&&(b=this.g,a[2]=b);null!==this.i&&(b=this.i,a[3]=b);null!==this.b&&(b=this.b,b=b.w(),a[4]=b);null!==this.h&&(b=this.h,a[5]=b);null!==this.c&&(b=this.c,b=b.w(),a[6]=b);return a};ot.prototype.getExtension=function(){return null};function ut(){return new ot} +function vt(a){if(null===a)var b=null;else{b=new ot;b.f=null;if(b.a)for(var c=0;c<b.a.length;c++){var d=b.a[c];d&&wt(d)}b.a=null;b.g=null;b.i=null;(c=b.b)&&kf(c);b.b=null;b.h=null;(c=b.c)&&xt(c);b.c=null;b.f=a.f;b.a=Bd(a.a,yt);b.g=a.g;b.i=a.i;b.b=a.b?jf(a.b):null;b.h=a.h;a.c?(a=a.c,c=new tt,xt(c),c.a=a.a?zt(a.a):null,a=c):a=null;b.c=a}return b}function At(){} +function Bt(a,b){for(;G(b);)switch(b.a){case 1:var c=L(b);a.f=c;break;case 2:c=new pt;O(b,c,Ct);a.a=a.a||[];a.a.push(c);break;case 3:c=J(b);a.g=c;break;case 4:c=K(b);a.i=c;break;case 5:c=new hf;O(b,c,lf);a.b=c;break;case 6:c=J(b);a.h=c;break;case 7:c=new tt;O(b,c,Dt);a.c=c;break;default:H(b)}} +function Et(a,b){if(a===b)b=!0;else if(null===a||null===b)b=!1;else{var c;if(c=a.f===b.f&&Dd(a.a,b.a,Ft)&&a.g===b.g&&a.i===b.i&&mf(a.b,b.b)&&a.h===b.h)a=a.c,b=b.c,c=a===b?!0:null===a||null===b?!1:Gt(a.a,b.a)?!0:!1;b=c?!0:!1}return b}ot.prototype.wa=function(){return null==this.f?"":this.f}; +pt.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}null!==this.a&&(b=this.a,b=b.slice(),a[1]=b);null!==this.g&&(b=this.g,a[2]=b);null!==this.i&&(b=this.i,a[3]=b);null!==this.f&&(b=this.f,a[4]=b);null!==this.c&&(b=this.c,b=b.w(),a[6]=b);null!==this.h&&(b=this.h,a[7]=b);return a};function wt(a){a.b=null;a.a=null;a.g=null;a.i=null;a.f=null;var b=a.c;b&&rf(b);a.c=null;a.h=null}pt.prototype.getExtension=function(){return null}; +function yt(a){if(null===a)a=null;else{var b=new pt;wt(b);b.b=a.b;b.a=Ad(a.a);b.g=a.g;b.i=a.i;b.f=a.f;if(a.c){var c=new qf;var d=a.c;rf(c);c.b=d.b?jf(d.b):null;c.a=d.a?jf(d.a):null}else c=null;b.c=c;b.h=a.h;a=b}return a}function Ct(a,b){for(;G(b);)switch(b.a){case 1:var c=L(b);a.b=c;break;case 2:c=L(b);a.a=a.a||[];a.a.push(c);break;case 3:c=L(b);a.g=c;break;case 4:c=L(b);a.i=c;break;case 5:c=b.c.da();a.f=c;break;case 7:c=new qf;O(b,c,sf);a.c=c;break;case 8:c=b.c.da();a.h=c;break;default:H(b)}} +function Ft(a,b){if(a===b)a=!0;else if(null===a||null===b)a=!1;else{var c;if(c=a.b===b.b&&Cd(a.a,b.a)&&a.g===b.g&&a.i===b.i&&a.f===b.f){c=a.c;var d=b.c;c=c===d?!0:null===c||null===d?!1:mf(c.b,d.b)&&mf(c.a,d.a)?!0:!1}a=c&&a.h===b.h?!0:!1}return a}pt.prototype.wa=function(){return null==this.b?"":this.b};qt.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;b=b.slice();a[0]=b}if(null!==this.a){b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[1]=b}return a}; +qt.prototype.getExtension=function(){return null};function Ht(){return new qt}function It(a){if(null===a)a=null;else{var b=new qt;b.b=null;if(b.a)for(var c=0;c<b.a.length;c++){var d=b.a[c];d&&(d.a=null,d.b=null)}b.a=null;b.b=Ad(a.b);b.a=Bd(a.a,Jt);a=b}return a}function Kt(){}function Lt(a,b){for(;G(b);)switch(b.a){case 1:var c=L(b);a.b=a.b||[];a.b.push(c);break;case 2:c=new rt;O(b,c,Mt);a.a=a.a||[];a.a.push(c);break;default:H(b)}} +function Nt(a,b){return a===b?!0:null===a||null===b?!1:Cd(a.b,b.b)&&Dd(a.a,b.a,Ot)?!0:!1}rt.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;a[0]=b}null!==this.b&&(b=this.b,a[1]=b);return a};rt.prototype.getExtension=function(){return null};function Jt(a){if(null===a)a=null;else{var b=new rt;b.a=null;b.b=null;b.a=a.a;b.b=a.b;a=b}return a}function Mt(a,b){for(;G(b);)switch(b.a){case 1:var c=L(b);a.a=c;break;case 2:c=b.c.da();a.b=c;break;default:H(b)}} +function Ot(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a||a.b!==b.b?!1:!0}st.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}null!==this.f&&(b=this.f,a[1]=b);null!==this.a&&(b=this.a,b=b.w(),a[2]=b);null!==this.c&&(b=this.c,a[3]=b);return a};function zt(a){var b=new st;Pt(b);b.b=a.b;b.f=a.f;b.a=a.a?bj(a.a):null;b.c=a.c;return b}function Pt(a){a.b=null;a.f=null;var b=a.a;b&&cj(b);a.a=null;a.c=null}st.prototype.getExtension=function(){return null}; +function Qt(a,b){for(;G(b);)switch(b.a){case 1:var c=L(b);a.b=c;break;case 2:c=L(b);a.f=c;break;case 3:c=new $i;O(b,c,dj);a.a=c;break;case 4:c=L(b);a.c=c;break;default:H(b)}}function Gt(a,b){return a===b?!0:null===a||null===b?!1:a.b===b.b&&a.f===b.f&&ej(a.a,b.a)&&a.c===b.c?!0:!1}tt.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.w();a[0]=b}return a};function xt(a){var b=a.a;b&&Pt(b);a.a=null}tt.prototype.getExtension=function(){return null}; +function Dt(a,b){for(;G(b);)switch(b.a){case 1:var c=new st;O(b,c,Qt);a.a=c;break;default:H(b)}};function Rt(){this.f=this.h=this.a=this.b=this.i=this.c=this.g=null}function St(){this.i=this.c=this.g=this.f=this.h=this.a=this.b=null}function Tt(){this.f=this.b=this.c=this.a=null}function Ut(){this.j=this.b=this.h=this.f=this.c=this.i=this.a=this.g=null}function Vt(){this.g=this.f=this.b=this.c=this.a=null} +function Wt(){this.g=this.f=this.G=this.H=this.K=this.A=this.B=this.J=this.s=this.l=this.O=this.C=this.D=this.M=this.v=this.m=this.I=this.j=this.a=this.L=this.u=this.c=this.h=this.o=this.i=this.b=null}function Xt(){this.I=this.f=this.G=this.H=this.A=this.B=this.C=this.g=this.o=this.h=this.m=this.u=this.s=this.i=this.v=this.D=this.l=this.c=this.b=this.a=this.j=null} +Rt.prototype.w=function(){var a=[];null!=this.c&&null==this.g&&(this.g=Gd(this.f,this.c,this.i));if(null!==this.g){var b=this.g;b=Dc(b);a[0]=b}null!=this.a&&null==this.b&&(this.b=Gd(this.f,this.a,this.h));null!==this.b&&(b=this.b,b=Dc(b),a[1]=b);return a};function Yt(a){a.g=null;a.c=null;a.i=null;a.b=null;a.a=null;a.h=null}Rt.prototype.getExtension=function(){return null};function Zt(a){a&&Yt(a)} +function $t(a,b){for(a.f=jd(b);G(b);)switch(b.a){case 1:null===a.c&&(a.c=b.b);kd(b);a.i=id(b);break;case 2:null===a.a&&(a.a=b.b);kd(b);a.h=id(b);break;case 1E3:H(b);break;case 1001:H(b);break;default:H(b)}}function au(a){return null!==a.g?Zc(a.g):a.f&&null!=a.c&&null!=a.i?(a=Zc(a.f,a.c,a.i-a.c),a.ca(),a.ca(),a):Zc()} +St.prototype.w=function(){var a=[];null!=this.a&&null==this.b&&(this.b=Gd(this.i,this.a,this.h));if(null!==this.b){var b=this.b;b=Dc(b);a[0]=b}null!==this.f&&(b=this.f,a[1]=b);null!==this.g&&(b=this.g,a[2]=b);null!==this.c&&(b=this.c,a[3]=b);return a};function bu(a){a.b=null;a.a=null;a.h=null;a.f=null;a.g=null;a.c=null}St.prototype.getExtension=function(){return null};function cu(a){a&&bu(a)} +function du(a,b){for(a.i=jd(b);G(b);)switch(b.a){case 1:null===a.a&&(a.a=b.b);kd(b);a.h=id(b);break;case 2:var c=J(b);a.f=c;break;case 3:c=J(b);a.g=c;break;case 4:c=J(b);a.c=c;break;case 1E3:H(b);break;default:H(b)}}Tt.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.w();a[0]=b}null!==this.c&&(b=this.c,a[1]=b);null!==this.b&&(b=this.b,a[3]=b);null!==this.f&&(b=this.f,b=b.w(),a[4]=b);return a};Tt.prototype.getExtension=function(){return null}; +function eu(a,b){for(;G(b);)switch(b.a){case 1:var c=new Rt;O(b,c,$t);a.a=c;break;case 2:c=N(b);a.c=c;break;case 4:c=J(b);a.b=c;break;case 5:c=new St;O(b,c,du);a.f=c;break;default:H(b)}}function fu(a){null===a.a&&(a.a=new Rt);return a.a}function gu(a){return null!=a.b?!0:!1} +Ut.prototype.w=function(){var a=[];null!=this.a&&null==this.g&&(this.g=Gd(this.j,this.a,this.i));if(null!==this.g){var b=this.g;b=Dc(b);a[0]=b}null!==this.c&&(b=this.c,a[1]=b);null!==this.f&&(b=this.f,a[2]=b);null!==this.h&&(b=this.h,a[3]=b);null!==this.b&&(b=this.b,a[4]=b);return a};Ut.prototype.getExtension=function(){return null}; +function hu(a,b){for(a.j=jd(b);G(b);)switch(b.a){case 1:null===a.a&&(a.a=b.b);kd(b);a.i=id(b);break;case 2:var c=J(b);a.c=c;break;case 3:c=J(b);a.f=c;break;case 4:c=N(b);a.h=c;break;case 5:c=J(b);a.b=c;break;case 1E3:H(b);break;default:H(b)}} +Vt.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[0]=b}null!==this.c&&(b=this.c,a[1]=b);null!==this.b&&(b=this.b,b=Oc(b,!0),a[2]=b);null!==this.f&&(b=this.f,a[3]=b);null!==this.g&&(b=this.g,a[999]=b);return a}; +function iu(a){if(a.a)for(var b=0;b<a.a.length;b++){var c=a.a[b];if(c){c.b=null;c.i=null;c.o=null;c.h=null;c.c=null;c.u=null;c.L=null;c.a=null;c.j=null;c.I=null;c.m=null;c.v=null;c.M=null;c.D=null;c.C=null;c.O=null;c.l=null;c.s=null;c.J=null;c.B=null;c.A=null;c.K=null;c.H=null;c.G=null;if(c.f)for(var d=0;d<c.f.length;d++)wd(c.f[d]);c.f=null}}a.a=null;a.c=null;a.b=null;a.f=null;a.g=null}Vt.prototype.getExtension=function(){return null}; +function ju(a,b){for(;G(b);)switch(b.a){case 1:var c=new Wt;O(b,c,ku);a.a=a.a||[];a.a.push(c);break;case 2:c=J(b);a.c=c;break;case 3:c=qd(b);a.b=c;break;case 4:c=N(b);a.f=c;break;case 1E3:c=J(b);a.g=c;break;default:H(b)}}function lu(a){return null==a.b?"\u00ffffffff\u00ffffff\u00ffff\u00ff\u00ffffffff\u00ffffff\u00ffff\u00ff":a.b}function mu(a){return null==a.f?1:a.f} +Wt.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}null!==this.i&&(b=this.i,a[1]=b);null!==this.o&&(b=this.o,a[2]=b);null!==this.h&&(b=this.h,b=Oc(b,!0),a[3]=b);nu(this);null!==this.c&&(b=this.c,b=b.slice(),a[5]=b);ou(this);null!==this.a&&(b=this.a,b=b.slice(),a[6]=b);pu(this);null!==this.m&&(b=this.m,b=b.slice(),a[7]=b);null!=this.C&&null==this.D&&(this.D=Fd(Wc.prototype.da,this.g,this.C,this.O));null!==this.D&&(b=this.D,b=b.slice(),a[8]=b);qu(this);null!==this.l&&(b=this.l, +b=b.slice(),a[9]=b);null!=this.A&&null==this.B&&(this.B=Fd(Wc.prototype.da,this.g,this.A,this.K));null!==this.B&&(b=this.B,b=b.slice(),a[10]=b);null!==this.H&&(b=this.H,a[999]=b);null!==this.G&&(b=this.G,a[1E3]=b);return a};var ru=[];Wt.prototype.getExtension=function(a){var b=!1;25E6<=a&&536870912>a&&(b=!0);return b?Id(this.f,a):null}; +function ku(a,b){for(a.g=jd(b);G(b);)switch(b.a){case 1:var c=L(b);a.b=c;break;case 2:c=J(b);a.i=c;break;case 3:c=K(b);a.o=c;break;case 4:c=qd(b);a.h=c;break;case 6:null===a.u&&(a.u=b.b);kd(b);a.L=id(b);break;case 7:null===a.j&&(a.j=b.b);kd(b);a.I=id(b);break;case 8:null===a.v&&(a.v=b.b);kd(b);a.M=id(b);break;case 9:null===a.C&&(a.C=b.b);kd(b);a.O=id(b);break;case 10:null===a.s&&(a.s=b.b);kd(b);a.J=id(b);break;case 11:null===a.A&&(a.A=b.b);kd(b);a.K=id(b);break;case 1E3:c=J(b);a.H=c;break;case 1001:c= +L(b);a.G=c;break;default:a.f=a.f||[],c=Jd(b,ru),a.f.push(c)}}function su(a){return null==a.b?"":a.b}function tu(a){return null!=a.c||null!=a.u?!0:!1}function uu(a){nu(a);return a.c?a.c.length:0}function vu(a,b){nu(a);return a.c[b]}function nu(a){null!=a.u&&null==a.c&&(a.c=Fd(Wc.prototype.Ma,a.g,a.u,a.L))}function ou(a){null!=a.j&&null==a.a&&(a.a=Fd(Wc.prototype.Ma,a.g,a.j,a.I))}function wu(a){return null!=a.m||null!=a.v?!0:!1}function xu(a,b){pu(a);return a.m[b]} +function pu(a){null!=a.v&&null==a.m&&(a.m=Fd(Wc.prototype.da,a.g,a.v,a.M))}function qu(a){null!=a.s&&null==a.l&&(a.l=Fd(Wc.prototype.da,a.g,a.s,a.J))} +Xt.prototype.w=function(){var a=[];if(null!==this.j){var b=this.j;b=b.w();a[0]=b}null!==this.a&&(b=this.a,b=b.w(),a[1]=b);null!==this.b&&(b=this.b,b=b.w(),a[2]=b);null!==this.c&&(b=this.c,b=b.w(),a[3]=b);null!==this.l&&(b=this.l,b=Oc(b,!0),a[4]=b);null!==this.D&&(b=this.D,a[5]=b);null!==this.v&&(b=this.v,a[6]=b);null!==this.i&&(b=this.i,a[7]=b);null!==this.s&&(b=this.s,a[8]=b);null!==this.u&&(b=this.u,a[9]=b);null!==this.m&&(b=this.m,a[10]=b);null!==this.h&&(b=this.h,a[11]=b);null!==this.o&&(b=this.o, +a[12]=b);null!==this.g&&(b=this.g,a[13]=b);null!==this.C&&(b=this.C,b=Oc(b,!1),a[14]=b);null!=this.A&&null==this.B&&(this.B=Fd(Wc.prototype.Ma,this.I,this.A,this.H));null!==this.B&&(b=this.B,b=b.slice(),a[15]=b);null!==this.G&&(b=this.G,a[999]=b);return a};var yu=[];Xt.prototype.getExtension=function(a){var b=!1;25E6<=a&&536870912>a&&(b=!0);return b?Id(this.f,a):null};function zu(a){a.f=a.f||[];return a.f} +function Au(a){if(a){var b=a.j;b&&iu(b);a.j=null;(b=a.a)&&iu(b);a.a=null;if(b=a.b)Zt(b.a),b.a=null,b.c=null,b.b=null,cu(b.f),b.f=null;a.b=null;if(b=a.c)b.g=null,b.a=null,b.i=null,b.c=null,b.f=null,b.h=null,b.b=null;a.c=null;a.l=null;a.D=null;a.v=null;a.i=null;a.s=null;a.u=null;a.m=null;a.h=null;a.o=null;a.g=null;a.C=null;a.B=null;a.A=null;a.H=null;a.G=null;if(a.f)for(b=0;b<a.f.length;b++)wd(a.f[b]);a.f=null}} +function Bu(a,b){for(a.I=jd(b);G(b);)switch(b.a){case 1:var c=new Vt;O(b,c,ju);a.j=c;break;case 2:c=new Vt;O(b,c,ju);a.a=c;break;case 3:c=new Tt;O(b,c,eu);a.b=c;break;case 4:c=new Ut;O(b,c,hu);a.c=c;break;case 5:c=qd(b);a.l=c;break;case 6:c=M(b);a.D=c;break;case 7:c=N(b);a.v=c;break;case 8:c=J(b);a.i=c;break;case 9:c=J(b);a.s=c;break;case 10:c=nd(b);a.u=c;break;case 11:c=J(b);a.m=c;break;case 12:c=J(b);a.h=c;break;case 13:c=J(b);a.o=c;break;case 14:c=J(b);a.g=c;break;case 15:c=pd(b);a.C=c;break;case 16:null=== +a.A&&(a.A=b.b);kd(b);a.H=id(b);break;case 1E3:c=J(b);a.G=c;break;default:a.f=a.f||[],c=Jd(b,yu),a.f.push(c)}}function Cu(a){null===a.j&&(a.j=new Vt);return a.j}function Du(a){null===a.a&&(a.a=new Vt);return a.a}function Eu(a){null===a.b&&(a.b=new Tt);return a.b}function Fu(a){null===a.c&&(a.c=new Ut);return a.c}function Gu(a){return null==a.l?"\u00ffffffff\u00ffffff\u00ffff\u00ff\u00ffffffff\u00ffffff\u00ffff\u00ff":a.l};function Hu(){this.l=this.i=this.b=this.c=this.h=this.j=this.g=this.a=this.f=null}function Iu(){this.g=this.f=this.c=this.a=this.b=null}function Ju(){this.a=this.b=null}function Ku(){this.h=this.f=this.g=this.j=this.c=this.b=this.a=this.i=null}function Lu(){this.f=this.g=this.c=this.a=this.b=null} +function Mu(){this.a=this.T=this.j=this.c=this.s=this.o=this.Y=this.K=this.u=this.O=this.B=this.g=this.W=this.J=this.m=this.U=this.G=this.l=this.Z=this.L=this.v=this.V=this.H=this.I=this.S=this.D=this.i=this.P=this.C=this.h=this.M=this.A=this.f=this.b=null}function Nu(){this.f=this.g=this.i=this.c=this.b=this.a=this.h=null}function Ou(){this.i=this.j=this.l=this.b=this.c=this.h=this.g=this.f=this.a=null} +function Pu(){this.B=this.l=this.u=this.s=this.v=this.i=this.A=this.j=this.g=this.h=this.m=this.a=this.c=this.b=this.o=this.f=null}function Qu(){this.c=this.f=this.g=this.b=this.i=this.j=this.h=this.a=null}function Ru(){this.f=this.c=this.g=this.h=this.a=this.b=null}function Su(){this.I=this.s=this.C=this.D=this.G=this.A=this.B=this.j=this.v=this.u=this.H=this.g=this.b=this.i=this.h=this.a=this.f=this.c=this.l=this.o=this.m=null} +function Tu(){this.v=this.o=this.a=this.b=this.s=this.h=this.m=this.u=this.j=this.l=this.f=this.c=this.i=this.g=null}function Uu(){this.B=this.m=this.u=this.o=this.s=this.b=this.v=this.f=this.A=this.i=this.c=this.g=this.h=this.l=this.j=this.a=null}function Vu(){this.b=this.a=null}function Wu(){this.b=this.a=null}function Xu(){this.b=this.c=this.a=null}function Yu(){this.c=this.f=this.b=this.g=this.a=null}function Zu(){this.h=this.g=this.c=this.f=this.a=this.b=null} +Hu.prototype.w=function(){var a=[];if(null!==this.f){var b=this.f;b=Oc(b,!1);a[0]=b}$u(this);if(null!==this.a){b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[1]=b}null!==this.h&&(b=this.h,a[2]=b);null!==this.c&&(b=this.c,a[3]=b);if(null!==this.b){b=this.b;b=b.slice();for(c=0;c<b.length;c++)b[c]=b[c].w();a[4]=b}null!==this.i&&(b=this.i,a[999]=b);return a};Hu.prototype.getExtension=function(){return null}; +function av(a,b){for(a.l=jd(b);G(b);)switch(b.a){case 1:var c=pd(b);a.f=c;break;case 2:null===a.g&&(a.g=b.b);kd(b);a.j=id(b);break;case 3:c=L(b);a.h=c;break;case 4:c=K(b);a.c=c;break;case 5:c=new Iu;O(b,c,bv);a.b=a.b||[];a.b.push(c);break;case 1E3:c=J(b);a.i=c;break;default:H(b)}}Hu.prototype.wa=function(){return null==this.f?"\x00\x00\x00\x00\x00\x00\x00\x00":this.f};function $u(a){null!=a.g&&null==a.a&&(a.a=Hd(cv,dv,a.l,a.g,a.j))} +Iu.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;b=b.slice();a[0]=b}null!=this.c&&null==this.a&&(this.a=Hd(cv,dv,this.g,this.c,this.f));if(null!==this.a){b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[1]=b}return a};Iu.prototype.getExtension=function(){return null};function ev(a){if(a){a.b=null;if(a.a)for(var b=0;b<a.a.length;b++)fv(a.a[b]);a.a=null;a.c=null;a.f=null}} +function bv(a,b){for(a.g=jd(b);G(b);)switch(b.a){case 1:var c=N(b);a.b=a.b||[];a.b.push(c);break;case 2:null===a.c&&(a.c=b.b);kd(b);a.f=id(b);break;default:H(b)}}Ju.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}null!==this.a&&(b=this.a,a[1]=b);return a};Ju.prototype.getExtension=function(){return null};function gv(){return new Ju}function hv(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.b=c;break;case 2:c=J(b);a.a=c;break;default:H(b)}} +Ku.prototype.w=function(){var a=[];if(null!==this.i){var b=this.i;a[0]=b}null!==this.a&&(b=this.a,b=b.w(),a[1]=b);null!==this.b&&(b=this.b,b=b.w(),a[2]=b);null!==this.c&&(b=this.c,b=b.w(),a[3]=b);null!==this.j&&(b=this.j,b=b.w(),a[4]=b);null!==this.g&&(b=this.g,b=b.w(),a[5]=b);null!==this.f&&(b=this.f,b=b.w(),a[7]=b);return a};var iv=[];Ku.prototype.getExtension=function(a){var b=!1;1E3<=a&&536870912>a&&(b=!0);return b?Id(this.h,a):null}; +function fv(a){if(a){a.i=null;var b=a.a;b&&jv(b);a.a=null;(b=a.b)&&kv(b);a.b=null;(b=a.c)&&lv(b);a.c=null;if(b=a.j){var c=b.a;c&&(c.a=null,c.b=null);b.a=null;b.c=null;b.b=null}a.j=null;(b=a.g)&&mv(b);a.g=null;(b=a.f)&&nv(b);a.f=null;if(a.h)for(b=0;b<a.h.length;b++)wd(a.h[b]);a.h=null}}function cv(){return new Ku} +function dv(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.i=c;break;case 2:c=new Ou;O(b,c,ov);a.a=c;break;case 3:c=new Pu;O(b,c,pv);a.b=c;break;case 4:c=new Uu;O(b,c,qv);a.c=c;break;case 5:c=new Xu;O(b,c,rv);a.j=c;break;case 6:c=new Yu;O(b,c,sv);a.g=c;break;case 8:c=new Zu;O(b,c,tv);a.f=c;break;default:a.h=a.h||[],c=Jd(b,iv),a.h.push(c)}}Ku.prototype.getZoom=function(){return null==this.i?0:this.i}; +Lu.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;b=Oc(b,!0);a[0]=b}uv(this);if(null!==this.a){b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[1]=b}return a};Lu.prototype.getExtension=function(){return null};function vv(a,b){for(a.f=jd(b);G(b);)switch(b.a){case 1:a.b=qd(b);break;case 2:null===a.c&&(a.c=b.b);kd(b);a.g=id(b);break;default:H(b)}}Lu.prototype.wa=function(){return null==this.b?"\x00\x00\x00\x00\x00\x00\x00\x00":this.b}; +function uv(a){null!=a.c&&null==a.a&&(a.a=Hd(wv,xv,a.f,a.c,a.g))} +function yv(a,b){for(a.a=jd(b);G(b);)switch(b.a){case 1:var c=new Lu;O(b,c,vv);a.b=a.b||[];a.b.push(c);break;case 2:null===a.A&&(a.A=b.b);kd(b);a.M=id(b);break;case 3:null===a.C&&(a.C=b.b);kd(b);a.P=id(b);break;case 4:null===a.D&&(a.D=b.b);kd(b);a.S=id(b);break;case 5:null===a.H&&(a.H=b.b);kd(b);a.V=id(b);break;case 6:null===a.L&&(a.L=b.b);kd(b);a.Z=id(b);break;case 7:null===a.G&&(a.G=b.b);kd(b);a.U=id(b);break;case 8:null===a.J&&(a.J=b.b);kd(b);a.W=id(b);break;case 9:null===a.B&&(a.B=b.b);kd(b); +a.O=id(b);break;case 10:null===a.K&&(a.K=b.b);kd(b);a.Y=id(b);break;case 11:c=L(b);a.o=c;break;case 12:c=L(b);a.s=c;break;case 13:null===a.j&&(a.j=b.b);kd(b);a.T=id(b);break;default:H(b)}} +Mu.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[0]=b}zv(this);if(null!==this.f){b=this.f;b=b.slice();for(c=0;c<b.length;c++)b[c]=b[c].w();a[1]=b}Av(this);if(null!==this.h){b=this.h;b=b.slice();for(c=0;c<b.length;c++)b[c]=b[c].w();a[2]=b}Bv(this);if(null!==this.i){b=this.i;b=b.slice();for(c=0;c<b.length;c++)b[c]=b[c].w();a[3]=b}Cv(this);if(null!==this.I){b=this.I;b=b.slice();for(c=0;c<b.length;c++)b[c]=b[c].w();a[4]=b}Dv(this); +if(null!==this.v){b=this.v;b=b.slice();for(c=0;c<b.length;c++)b[c]=b[c].w();a[5]=b}Ev(this);if(null!==this.l){b=this.l;b=b.slice();for(c=0;c<b.length;c++)b[c]=b[c].w();a[6]=b}Fv(this);if(null!==this.m){b=this.m;b=b.slice();for(c=0;c<b.length;c++)b[c]=b[c].w();a[7]=b}Gv(this);if(null!==this.g){b=this.g;b=b.slice();for(c=0;c<b.length;c++)b[c]=b[c].w();a[8]=b}Hv(this);null!==this.u&&(b=this.u,b=b.slice(),a[9]=b);null!==this.o&&(b=this.o,a[10]=b);null!==this.s&&(b=this.s,a[11]=b);Iv(this);if(null!==this.c){b= +this.c;b=b.slice();for(c=0;c<b.length;c++)b[c]=b[c].w();a[12]=b}return a};Mu.prototype.getExtension=function(){return null};function zv(a){null!=a.A&&null==a.f&&(a.f=Hd(Jv,ov,a.a,a.A,a.M))}function Av(a){null!=a.C&&null==a.h&&(a.h=Hd(Kv,pv,a.a,a.C,a.P))}function Bv(a){null!=a.D&&null==a.i&&(a.i=Hd(Lv,qv,a.a,a.D,a.S))}function Cv(a){null!=a.H&&null==a.I&&(a.I=Hd(Mv,rv,a.a,a.H,a.V))}function Dv(a){null!=a.L&&null==a.v&&(a.v=Hd(Nv,sv,a.a,a.L,a.Z))} +function Ev(a){null!=a.G&&null==a.l&&(a.l=Hd(Ov,tv,a.a,a.G,a.U))}function Pv(a,b){Fv(a);return a.m[b]}function Fv(a){null!=a.J&&null==a.m&&(a.m=Hd(Qv,Rv,a.a,a.J,a.W))}function Sv(a,b){Gv(a);return a.g[b]}function Gv(a){null!=a.B&&null==a.g&&(a.g=Hd(Tv,Uv,a.a,a.B,a.O))}function Hv(a){if(null!=a.K&&null==a.u){var b=a.a,c=a.K,d=a.Y;var e=Wc.prototype.Lf;if(b&&null!=c&&null!=d){b=Zc(b,c,d-c);for(c=[];!b.kb();)b.ca(),c.push(e.call(b));Vc(b);e=c}else e=null;a.u=e}} +function Iv(a){null!=a.j&&null==a.c&&(a.c=Hd(gv,hv,a.a,a.j,a.T))}Nu.prototype.w=function(){var a=[];if(null!==this.h){var b=this.h;a[0]=b}null!==this.a&&(b=this.a,a[1]=b);null!==this.b&&(b=this.b,a[2]=b);null!==this.c&&(b=this.c,a[3]=b);null!==this.i&&(b=this.i,a[4]=b);null!==this.g&&(b=this.g,a[5]=b);null!==this.f&&(b=this.f,a[6]=b);return a};Nu.prototype.getExtension=function(){return null};function wv(){return new Nu} +function xv(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.h=c;break;case 2:c=J(b);a.a=c;break;case 3:c=J(b);a.b=c;break;case 4:c=J(b);a.c=c;break;case 5:c=J(b);a.i=c;break;case 6:c=J(b);a.g=c;break;case 7:c=J(b);a.f=c;break;default:H(b)}}Nu.prototype.getZoom=function(){return null==this.h?0:this.h}; +Ou.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[0]=b}null!==this.f&&(b=this.f,a[1]=b);null!==this.g&&(b=this.g,a[2]=b);null!==this.h&&(b=this.h,a[3]=b);null!==this.c&&(b=this.c,a[4]=b);null!==this.b&&(b=this.b,b=b.slice(),a[5]=b);null!==this.l&&(b=this.l,a[6]=b);null!==this.j&&(b=this.j,a[7]=b);null!==this.i&&(b=this.i,a[8]=b);return a}; +function jv(a){if(a.a)for(var b=0;b<a.a.length;b++){var c=a.a[b];c&&Vv(c)}a.a=null;a.f=null;a.g=null;a.h=null;a.c=null;a.b=null;a.l=null;a.j=null;a.i=null}Ou.prototype.getExtension=function(){return null};function Jv(){return new Ou} +function ov(a,b){for(;G(b);)switch(b.a){case 1:var c=new Tu;O(b,c,Rv);a.a=a.a||[];a.a.push(c);break;case 2:c=nd(b);a.f=c;break;case 3:c=J(b);a.g=c;break;case 4:c=K(b);a.h=c;break;case 5:c=K(b);a.c=c;break;case 6:c=J(b);a.b=a.b||[];a.b.push(c);break;case 7:c=L(b);a.l=c;break;case 8:c=J(b);a.j=c;break;case 9:c=J(b);a.i=c;break;default:H(b)}} +Pu.prototype.w=function(){var a=[];if(null!==this.f){var b=this.f;a[0]=b}null!==this.o&&(b=this.o,a[1]=b);if(null!==this.b){b=this.b;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[2]=b}null!==this.c&&(b=this.c,b=b.w(),a[3]=b);null!==this.a&&(b=this.a,b=b.w(),a[4]=b);null!==this.m&&(b=this.m,a[5]=b);null!==this.h&&(b=this.h,a[6]=b);Wv(this);null!==this.g&&(b=this.g,b=b.slice(),a[7]=b);null!==this.i&&(b=this.i,a[8]=b);null!==this.v&&(b=this.v,a[9]=b);null!==this.s&&(b=this.s,a[10]=b);null!== +this.u&&(b=this.u,a[11]=b);null!==this.l&&(b=this.l,a[12]=b);return a}; +function Xv(a,b){kv(a);a.f=b.f;a.o=b.o;a.b=Bd(b.b,Yv);if(b.c){var c=b.c;var d=new Ru;Zv(d);d.b=c.b;d.a=c.a;d.h=c.h;d.g=c.g;d.c=c.c;d.f=c.f;c=d}else c=null;a.c=c;b.a?(c=b.a,d=new Su,$v(d),d.m=c.m,d.o=c.o,d.l=c.l,d.c=c.c,d.f=c.f,d.a=Bd(c.a,Yv),d.h=c.h,d.i=c.i,d.b=Ad(c.b),d.g=c.g,d.H=c.H,d.u=c.u,d.v=c.v,d.j=Ad(c.j),d.B=c.B,d.A=c.A,d.G=c.G,d.D=c.D,d.C=c.C,d.s=c.s,d.I=c.I,c=d):c=null;a.a=c;a.m=b.m;a.h=b.h;a.g=Ad(b.g);a.j=b.j;a.A=b.A;a.i=b.i;a.v=b.v;a.s=b.s;a.u=b.u;a.l=b.l;a.B=b.B} +function kv(a){a.f=null;a.o=null;if(a.b)for(var b=0;b<a.b.length;b++){var c=a.b[b];c&&aw(c)}a.b=null;(b=a.c)&&Zv(b);a.c=null;(b=a.a)&&$v(b);a.a=null;a.m=null;a.h=null;a.g=null;a.j=null;a.A=null;a.i=null;a.v=null;a.s=null;a.u=null;a.l=null}Pu.prototype.getExtension=function(){return null};function Kv(){return new Pu} +function pv(a,b){for(a.B=jd(b);G(b);)switch(b.a){case 1:var c=nd(b);a.f=c;break;case 2:c=nd(b);a.o=c;break;case 3:c=new Qu;O(b,c,Uv);a.b=a.b||[];a.b.push(c);break;case 4:c=new Ru;O(b,c,bw);a.c=c;break;case 5:c=new Su;O(b,c,cw);a.a=c;break;case 6:c=J(b);a.m=c;break;case 7:c=K(b);a.h=c;break;case 8:null===a.j&&(a.j=b.b);kd(b);a.A=id(b);break;case 9:c=N(b);a.i=c;break;case 10:c=N(b);a.v=c;break;case 11:c=b.c.da();a.s=c;break;case 12:c=b.c.da();a.u=c;break;case 13:c=b.c.da();a.l=c;break;default:H(b)}} +function dw(a){null===a.c&&(a.c=new Ru);return a.c}function ew(a){null===a.a&&(a.a=new Su);return a.a}function Wv(a){null!=a.j&&null==a.g&&(a.g=Fd(Wc.prototype.Ma,a.B,a.j,a.A))}Qu.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;a[0]=b}null!==this.h&&(b=this.h,a[1]=b);null!==this.j&&(b=this.j,a[2]=b);null!==this.i&&(b=this.i,a[3]=b);null!==this.b&&(b=this.b,a[4]=b);null!==this.g&&(b=this.g,a[5]=b);null!==this.f&&(b=this.f,a[6]=b);return a}; +function aw(a){a.a=null;a.h=null;a.j=null;a.i=null;a.b=null;a.g=null;a.f=null;if(a.c)for(var b=0;b<a.c.length;b++)wd(a.c[b]);a.c=null}var fw=[];Qu.prototype.getExtension=function(a){var b=!1;1E6<=a&&536870912>a&&(b=!0);return b?Id(this.c,a):null};function Tv(){return new Qu}function Yv(a){if(null===a)a=null;else{var b=new Qu;aw(b);b.a=a.a;b.h=a.h;b.j=a.j;b.i=a.i;b.b=a.b;b.g=a.g;b.f=a.f;b.c=xd(a.c);a=b}return a} +function Uv(a,b){for(;G(b);)switch(b.a){case 1:var c=L(b);a.a=c;break;case 2:c=J(b);a.h=c;break;case 3:c=J(b);a.j=c;break;case 4:c=J(b);a.i=c;break;case 5:c=J(b);a.b=c;break;case 6:c=nd(b);a.g=c;break;case 7:c=nd(b);a.f=c;break;default:a.c=a.c||[],c=Jd(b,fw),a.c.push(c)}} +Ru.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}null!==this.a&&(b=this.a,a[1]=b);null!==this.h&&(b=this.h,a[2]=b);null!==this.g&&(b=this.g,a[3]=b);null!==this.c&&(b=this.c,a[4]=b);null!==this.f&&(b=this.f,a[5]=b);return a};function Zv(a){a.b=null;a.a=null;a.h=null;a.g=null;a.c=null;a.f=null}Ru.prototype.getExtension=function(){return null}; +function bw(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.b=c;break;case 2:c=J(b);a.a=c;break;case 3:c=J(b);a.h=c;break;case 4:c=J(b);a.g=c;break;case 5:c=L(b);a.c=c;break;case 6:c=J(b);a.f=c;break;default:H(b)}} +Su.prototype.w=function(){var a=[];if(null!==this.m){var b=this.m;a[0]=b}null!==this.o&&(b=this.o,a[1]=b);null!==this.l&&(b=this.l,a[2]=b);null!==this.c&&(b=this.c,a[3]=b);null!==this.f&&(b=this.f,a[4]=b);if(null!==this.a){b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[5]=b}null!==this.h&&(b=this.h,a[6]=b);null!==this.i&&(b=this.i,a[7]=b);gw(this);null!==this.b&&(b=this.b,b=b.slice(),a[8]=b);null!==this.u&&(b=this.u,a[9]=b);null!==this.v&&(b=this.v,a[10]=b);null!==this.j&&(b=this.j, +b=b.slice(),a[11]=b);null!==this.B&&(b=this.B,a[12]=b);null!==this.A&&(b=this.A,a[13]=b);null!==this.G&&(b=this.G,a[14]=b);null!==this.D&&(b=this.D,a[15]=b);null!==this.C&&(b=this.C,a[16]=b);null!==this.s&&(b=this.s,a[17]=b);return a};function $v(a){a.m=null;a.o=null;a.l=null;a.c=null;a.f=null;if(a.a)for(var b=0;b<a.a.length;b++){var c=a.a[b];c&&aw(c)}a.a=null;a.h=null;a.i=null;a.b=null;a.g=null;a.H=null;a.u=null;a.v=null;a.j=null;a.B=null;a.A=null;a.G=null;a.D=null;a.C=null;a.s=null} +Su.prototype.getExtension=function(){return null}; +function cw(a,b){for(a.I=jd(b);G(b);)switch(b.a){case 1:var c=nd(b);a.m=c;break;case 2:c=J(b);a.o=c;break;case 3:c=nd(b);a.l=c;break;case 4:c=J(b);a.c=c;break;case 5:c=J(b);a.f=c;break;case 6:c=new Qu;O(b,c,Uv);a.a=a.a||[];a.a.push(c);break;case 7:c=md(b);a.h=c;break;case 8:c=md(b);a.i=c;break;case 9:null===a.g&&(a.g=b.b);kd(b);a.H=id(b);break;case 10:c=J(b);a.u=c;break;case 11:c=J(b);a.v=c;break;case 12:c=N(b);a.j=a.j||[];a.j.push(c);break;case 13:c=J(b);a.B=c;break;case 14:c=J(b);a.A=c;break;case 15:c= +N(b);a.G=c;break;case 16:c=J(b);a.D=c;break;case 17:c=nd(b);a.C=c;break;case 18:c=K(b);a.s=c;break;default:H(b)}}function gw(a){null!=a.g&&null==a.b&&(a.b=Fd(Wc.prototype.Ma,a.I,a.g,a.H))} +Tu.prototype.w=function(){var a=[];if(null!==this.g){var b=this.g;a[0]=b}null!==this.i&&(b=this.i,a[1]=b);null!==this.c&&(b=this.c,b=b.slice(),a[2]=b);null!==this.f&&(b=this.f,a[3]=b);null!=this.j&&null==this.l&&(this.l=Fd(Wc.prototype.Eb,this.v,this.j,this.u));null!==this.l&&(b=this.l,b=b.slice(),a[4]=b);null!==this.m&&(b=this.m,a[5]=b);null!==this.h&&(b=this.h,a[7]=b);null!==this.s&&(b=this.s,a[8]=b);null!==this.b&&(b=this.b,b=b.w(),a[9]=b);null!==this.a&&(b=this.a,b=b.w(),a[10]=b);null!==this.o&& +(b=this.o,a[11]=b);return a};function Vv(a){a.g=null;a.i=null;a.c=null;a.f=null;a.l=null;a.j=null;a.u=null;a.m=null;a.h=null;a.s=null;var b=a.b;b&&(b.a=null,b.b=null);a.b=null;if(b=a.a)b.a=null,b.b=null;a.a=null;a.o=null}Tu.prototype.getExtension=function(){return null};function Qv(){return new Tu} +function hw(a){if(null===a)a=null;else{var b=new Tu;Vv(b);b.g=a.g;b.i=a.i;b.c=Ad(a.c);b.f=a.f;b.l=Ad(a.l);b.j=a.j;b.u=a.u;b.m=a.m;b.h=a.h;b.s=a.s;b.b=a.b?iw(a.b):null;b.a=a.a?iw(a.a):null;b.o=a.o;b.v=a.v;a=b}return a} +function Rv(a,b){for(a.v=jd(b);G(b);)switch(b.a){case 1:var c=nd(b);a.g=c;break;case 2:c=J(b);a.i=c;break;case 3:c=J(b);a.c=a.c||[];a.c.push(c);break;case 4:c=L(b);a.f=c;break;case 5:null===a.j&&(a.j=b.b);kd(b);a.u=id(b);break;case 6:c=J(b);a.m=c;break;case 8:c=b.c.da();a.h=c;break;case 9:c=J(b);a.s=c;break;case 10:c=new Vu;O(b,c,jw);a.b=c;break;case 11:c=new Vu;O(b,c,jw);a.a=c;break;case 12:c=J(b);a.o=c;break;default:H(b)}} +Uu.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[0]=b}null!==this.j&&(b=this.j,a[1]=b);null!==this.l&&(b=this.l,a[2]=b);null!==this.h&&(b=this.h,a[3]=b);null!==this.g&&(b=this.g,a[4]=b);kw(this);null!==this.c&&(b=this.c,b=b.slice(),a[5]=b);null!==this.f&&(b=this.f,a[6]=b);null!==this.v&&(b=this.v,a[7]=b);null!==this.b&&(b=this.b,a[8]=b);null!==this.s&&(b=this.s,a[9]=b);null!==this.o&&(b=this.o,a[10]=b);null!==this.u&&(b=this.u, +a[11]=b);null!==this.m&&(b=this.m,a[12]=b);return a};function lv(a){if(a.a)for(var b=0;b<a.a.length;b++){var c=a.a[b];c&&Vv(c)}a.a=null;a.j=null;a.l=null;a.h=null;a.g=null;a.c=null;a.i=null;a.A=null;a.f=null;a.v=null;a.b=null;a.s=null;a.o=null;a.u=null;a.m=null}Uu.prototype.getExtension=function(){return null};function Lv(){return new Uu} +function qv(a,b){for(a.B=jd(b);G(b);)switch(b.a){case 1:var c=new Tu;O(b,c,Rv);a.a=a.a||[];a.a.push(c);break;case 2:c=nd(b);a.j=c;break;case 3:c=J(b);a.l=c;break;case 4:c=J(b);a.h=c;break;case 5:c=K(b);a.g=c;break;case 6:null===a.i&&(a.i=b.b);kd(b);a.A=id(b);break;case 7:c=L(b);a.f=c;break;case 8:c=J(b);a.v=c;break;case 9:c=L(b);a.b=c;break;case 10:c=J(b);a.s=c;break;case 11:c=md(b);a.o=c;break;case 12:c=J(b);a.u=c;break;case 13:c=md(b);a.m=c;break;default:H(b)}} +function kw(a){null!=a.i&&null==a.c&&(a.c=Fd(Wc.prototype.Ma,a.B,a.i,a.A))}Vu.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;a[0]=b}null!==this.b&&(b=this.b,a[2]=b);return a};function iw(a){var b=new Vu;b.a=null;b.b=null;b.a=a.a;b.b=a.b;return b}Vu.prototype.getExtension=function(){return null};function jw(a,b){for(;G(b);)switch(b.a){case 1:var c=L(b);a.a=c;break;case 3:c=J(b);a.b=c;break;default:H(b)}} +Wu.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;a[0]=b}null!==this.b&&(b=this.b,a[1]=b);return a};Wu.prototype.getExtension=function(){return null};function lw(a,b){for(;G(b);)switch(b.a){case 1:var c=nd(b);a.a=c;break;case 2:c=nd(b);a.b=c;break;default:H(b)}}Xu.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.w();a[0]=b}null!==this.c&&(b=this.c,a[1]=b);null!==this.b&&(b=this.b,a[2]=b);return a};Xu.prototype.getExtension=function(){return null}; +function Mv(){return new Xu}function rv(a,b){for(;G(b);)switch(b.a){case 1:var c=new Wu;O(b,c,lw);a.a=c;break;case 2:c=J(b);a.c=c;break;case 3:c=K(b);a.b=c;break;default:H(b)}}Yu.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;a[0]=b}null!==this.g&&(b=this.g,a[1]=b);null!==this.b&&(b=this.b,a[2]=b);null!==this.f&&(b=this.f,a[3]=b);null!==this.c&&(b=this.c,a[4]=b);return a};function mv(a){a.a=null;a.g=null;a.b=null;a.f=null;a.c=null}Yu.prototype.getExtension=function(){return null}; +function Nv(){return new Yu}function sv(a,b){for(;G(b);)switch(b.a){case 1:var c=nd(b);a.a=c;break;case 2:c=J(b);a.g=c;break;case 3:c=nd(b);a.b=c;break;case 4:c=J(b);a.f=c;break;case 5:c=K(b);a.c=c;break;default:H(b)}}Zu.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[1]=b}null!==this.a&&(b=this.a,a[2]=b);null!=this.c&&null==this.f&&(this.f=Fd(Wc.prototype.zd,this.h,this.c,this.g));null!==this.f&&(b=this.f,b=b.slice(),a[3]=b);return a}; +function nv(a){a.b=null;a.a=null;a.f=null;a.c=null;a.g=null}Zu.prototype.getExtension=function(){return null};function Ov(){return new Zu}function tv(a,b){for(a.h=jd(b);G(b);)switch(b.a){case 2:var c=J(b);a.b=c;break;case 3:c=K(b);a.a=c;break;case 4:null===a.c&&(a.c=b.b);kd(b);a.g=id(b);break;default:H(b)}};function mw(){this.f=this.b=this.a=this.c=null}mw.prototype.w=function(){var a=[];if(null!==this.c){var b=this.c;a[0]=b}null!==this.a&&(b=this.a,a[1]=b);null!==this.b&&(b=this.b,a[2]=b);null!==this.f&&(b=this.f,a[3]=b);return a};mw.prototype.getExtension=function(){return null};function nw(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.c=c;break;case 2:c=J(b);a.a=c;break;case 3:c=J(b);a.b=c;break;case 4:c=J(b);a.f=c;break;default:H(b)}}mw.prototype.getZoom=function(){return null==this.c?0:this.c};function ow(){this.g=this.b=this.J=this.D=this.H=this.I=this.L=this.A=this.B=this.h=this.C=this.G=this.l=this.i=this.o=this.u=this.s=this.m=this.K=this.j=this.a=this.v=this.c=this.f=null}function pw(){this.a=this.T=this.I=this.J=this.V=this.G=this.B=this.L=this.j=this.m=this.U=this.D=this.v=this.K=this.i=this.l=this.M=this.c=this.b=this.O=this.o=this.h=this.S=this.C=this.g=this.P=this.A=this.f=this.H=this.s=this.u=null} +function qw(){this.b=this.v=this.m=this.s=this.u=this.l=this.g=this.c=this.o=this.j=this.i=this.h=this.f=this.a=null}function rw(){this.b=this.c=this.a=null}function sw(){this.b=this.g=this.A=this.i=this.a=this.v=this.j=this.l=this.B=this.o=this.f=this.C=this.s=this.u=this.m=this.c=this.h=null}function tw(){this.b=this.s=this.m=this.o=this.f=this.l=this.j=this.i=this.h=this.g=this.c=this.a=null}function uw(){this.o=this.a=this.l=this.b=this.h=this.g=this.f=this.j=this.m=this.i=this.c=null} +function vw(){this.j=this.g=this.f=this.a=this.i=this.b=this.c=this.h=null}function ww(){this.a=this.i=this.f=this.c=this.j=this.h=this.g=this.b=null}function xw(){this.i=this.c=this.f=this.h=this.a=this.b=this.g=null}function yw(){this.a=this.b=this.c=this.g=this.f=null}function zw(){this.g=this.a=this.f=this.c=this.b=null}function Aw(){this.a=this.b=null}function Bw(){this.b=this.c=this.a=null}function Cw(){this.h=this.a=this.g=this.b=this.c=this.f=null}function Dw(){this.a=null} +function Ew(){}function Fw(){this.b=this.a=null}function Gw(){this.b=this.a=null}function Hw(){this.b=this.a=null}function Iw(){this.b=this.a=null}function Jw(){this.Aa=null}function Kw(){this.b=this.a=null}function Lw(){this.a=this.b=null}function Mw(){this.g=this.s=this.m=this.B=this.v=this.A=this.a=this.l=this.i=this.j=this.o=this.C=this.f=this.h=this.b=this.u=this.c=null} +ow.prototype.w=function(){var a=[];null!=this.c&&null==this.f&&(this.f=Gd(this.g,this.c,this.v));if(null!==this.f){var b=this.f;b=Dc(b);a[0]=b}Nw(this);null!==this.a&&(b=this.a,b=b.slice(),a[1]=b);null!==this.m&&(b=this.m,a[2]=b);null!==this.s&&(b=this.s,a[3]=b);null!==this.u&&(b=this.u,a[4]=b);null!==this.o&&(b=this.o,a[5]=b);null!==this.i&&(b=this.i,a[6]=b);null!==this.l&&(b=this.l,a[7]=b);null!==this.G&&(b=this.G,a[8]=b);null!==this.C&&(b=this.C,a[9]=b);null!==this.h&&(b=this.h,b=Oc(b,!0),a[10]= +b);null!=this.A&&null==this.B&&(this.B=Fd(Wc.prototype.De,this.g,this.A,this.L));null!==this.B&&(b=this.B,b=b.slice(),b=Pc(b,!0),a[11]=b);null!==this.I&&(b=this.I,a[12]=b);null!==this.H&&(b=this.H,a[13]=b);null!==this.D&&(b=this.D,a[14]=b);null!==this.J&&(b=this.J,a[1E3]=b);return a};var Ow=[];ow.prototype.getExtension=function(a){var b=!1;25E6<=a&&536870912>a&&(b=!0);return b?Id(this.b,a):null};function Pw(a){a.b=a.b||[];return a.b} +function Qw(a){if(a){a.f=null;a.c=null;a.v=null;a.a=null;a.j=null;a.K=null;a.m=null;a.s=null;a.u=null;a.o=null;a.i=null;a.l=null;a.G=null;a.C=null;a.h=null;a.B=null;a.A=null;a.L=null;a.I=null;a.H=null;a.D=null;a.J=null;if(a.b)for(var b=0;b<a.b.length;b++)wd(a.b[b]);a.b=null}} +function Rw(a,b){for(a.g=jd(b);G(b);)switch(b.a){case 1:null===a.c&&(a.c=b.b);kd(b);a.v=id(b);break;case 2:null===a.j&&(a.j=b.b);kd(b);a.K=id(b);break;case 3:var c=J(b);a.m=c;break;case 4:c=J(b);a.s=c;break;case 5:c=nd(b);a.u=c;break;case 6:c=N(b);a.o=c;break;case 7:c=J(b);a.i=c;break;case 8:c=N(b);a.l=c;break;case 9:c=M(b);a.G=c;break;case 10:c=J(b);a.C=c;break;case 11:c=qd(b);a.h=c;break;case 12:null===a.A&&(a.A=b.b);kd(b);a.L=id(b);break;case 13:c=J(b);a.I=c;break;case 14:c=J(b);a.H=c;break;case 15:c= +N(b);a.D=c;break;case 1001:c=J(b);a.J=c;break;case 1E3:H(b);break;default:a.b=a.b||[],c=Jd(b,Ow),a.b.push(c)}}function Sw(a){return null!==a.f?Zc(a.f):a.g&&null!=a.c&&null!=a.v?(a=Zc(a.g,a.c,a.v-a.c),a.ca(),a.ca(),a):Zc()}function Tw(a){return null!=a.a||null!=a.j?!0:!1}function Uw(a){Nw(a);return a.a?a.a.length:0}function Nw(a){null!=a.j&&null==a.a&&(a.a=Fd(Wc.prototype.Ma,a.g,a.j,a.K))}function Vw(a){return null==a.o?1:a.o}function Ww(a){return null==a.l?1:a.l} +pw.prototype.w=function(){var a=[];null!=this.s&&null==this.u&&(this.u=Gd(this.a,this.s,this.H));if(null!==this.u){var b=this.u;b=Dc(b);a[0]=b}Xw(this);null!==this.f&&(b=this.f,b=b.slice(),a[1]=b);Yw(this);null!==this.g&&(b=this.g,b=b.slice(),a[2]=b);Zw(this);null!==this.h&&(b=this.h,b=b.slice(),a[3]=b);null!==this.b&&(b=this.b,a[4]=b);null!==this.c&&(b=this.c,a[5]=b);null!==this.M&&(b=this.M,a[6]=b);null!=this.i&&null==this.l&&(this.l=Gd(this.a,this.i,this.K));null!==this.l&&(b=this.l,b=Dc(b),a[7]= +b);$w(this);null!==this.v&&(b=this.v,b=b.slice(),a[8]=b);null!=this.j&&null==this.m&&(this.m=Gd(this.a,this.j,this.L));null!==this.m&&(b=this.m,b=Dc(b),a[9]=b);ax(this);null!==this.B&&(b=this.B,b=b.slice(),a[10]=b);null!=this.I&&null==this.J&&(this.J=Fd(Wc.prototype.zd,this.a,this.I,this.T));null!==this.J&&(b=this.J,b=b.slice(),a[11]=b);return a}; +function bx(a){a.u=null;a.s=null;a.H=null;a.f=null;a.A=null;a.P=null;a.g=null;a.C=null;a.S=null;a.h=null;a.o=null;a.O=null;a.b=null;a.c=null;a.M=null;a.l=null;a.i=null;a.K=null;a.v=null;a.D=null;a.U=null;a.m=null;a.j=null;a.L=null;a.B=null;a.G=null;a.V=null;a.J=null;a.I=null;a.T=null}pw.prototype.getExtension=function(){return null};function cx(a){a&&bx(a)} +function dx(a,b){for(a.a=jd(b);G(b);)switch(b.a){case 1:null===a.s&&(a.s=b.b);kd(b);a.H=id(b);break;case 2:null===a.A&&(a.A=b.b);kd(b);a.P=id(b);break;case 3:null===a.C&&(a.C=b.b);kd(b);a.S=id(b);break;case 4:null===a.o&&(a.o=b.b);kd(b);a.O=id(b);break;case 5:var c=J(b);a.b=c;break;case 6:c=J(b);a.c=c;break;case 7:c=J(b);a.M=c;break;case 8:null===a.i&&(a.i=b.b);kd(b);a.K=id(b);break;case 9:null===a.D&&(a.D=b.b);kd(b);a.U=id(b);break;case 10:null===a.j&&(a.j=b.b);kd(b);a.L=id(b);break;case 11:null=== +a.G&&(a.G=b.b);kd(b);a.V=id(b);break;case 12:null===a.I&&(a.I=b.b);kd(b);a.T=id(b);break;case 1E3:H(b);break;case 1001:H(b);break;case 1002:H(b);break;default:H(b)}}function ex(a){return null!==a.u?Zc(a.u):a.a&&null!=a.s&&null!=a.H?(a=Zc(a.a,a.s,a.H-a.s),a.ca(),a.ca(),a):Zc()}function fx(a){return null!=a.f||null!=a.A?!0:!1}function gx(a){Xw(a);return a.f?a.f.length:0}function hx(a){Xw(a);return a.f}function ix(a){return null===a.f?zd(a.a,a.A,a.P):Tc(null,null,a.f)} +function Xw(a){null!=a.A&&null==a.f&&(a.f=Fd(Wc.prototype.Ma,a.a,a.A,a.P))}function jx(a){Yw(a);return a.g?a.g.length:0}function kx(a){Yw(a);return a.g}function Yw(a){null!=a.C&&null==a.g&&(a.g=Fd(Wc.prototype.Ma,a.a,a.C,a.S))}function lx(a){Zw(a);return a.h}function Zw(a){null!=a.o&&null==a.h&&(a.h=Fd(Wc.prototype.Ma,a.a,a.o,a.O))}function mx(a){return null!==a.l?Zc(a.l):a.a&&null!=a.i&&null!=a.K?(a=Zc(a.a,a.i,a.K-a.i),a.ca(),a.ca(),a):Zc()}function nx(a){$w(a);return a.v} +function $w(a){null!=a.D&&null==a.v&&(a.v=Fd(Wc.prototype.Ma,a.a,a.D,a.U))}function ox(a){return null!==a.m?Zc(a.m):a.a&&null!=a.j&&null!=a.L?(a=Zc(a.a,a.j,a.L-a.j),a.ca(),a.ca(),a):Zc()}function px(a){ax(a);return a.B}function ax(a){null!=a.G&&null==a.B&&(a.B=Fd(Wc.prototype.Ma,a.a,a.G,a.V))} +qw.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.w();a[0]=b}null!==this.f&&(b=this.f,a[1]=b);null!==this.h&&(b=this.h,a[2]=b);null!==this.i&&(b=this.i,a[3]=b);null!==this.j&&(b=this.j,a[4]=b);null!==this.o&&(b=this.o,a[5]=b);null!==this.c&&(b=this.c,a[6]=b);null!==this.g&&(b=this.g,b=Oc(b,!0),a[7]=b);null!==this.l&&(b=this.l,b=Oc(b,!1),a[9]=b);null!==this.u&&(b=this.u,a[10]=b);null!==this.s&&(b=this.s,a[11]=b);null!==this.m&&(b=this.m,a[12]=b);null!==this.v&&(b=this.v,a[999]= +b);return a};var qx=[];qw.prototype.getExtension=function(a){var b=!1;25E6<=a&&536870912>a&&(b=!0);return b?Id(this.b,a):null};function rx(a){a.b=a.b||[];return a.b}function sx(a){if(a){cx(a.a);a.a=null;a.f=null;a.h=null;a.i=null;a.j=null;a.o=null;a.c=null;a.g=null;a.l=null;a.u=null;a.s=null;a.m=null;a.v=null;if(a.b)for(var b=0;b<a.b.length;b++)wd(a.b[b]);a.b=null}} +function tx(a,b){for(;G(b);)switch(b.a){case 1:var c=new pw;O(b,c,dx);a.a=c;break;case 2:c=K(b);a.f=c;break;case 3:c=J(b);a.h=c;break;case 4:c=J(b);a.i=c;break;case 5:c=nd(b);a.j=c;break;case 6:c=M(b);a.o=c;break;case 7:c=K(b);a.c=c;break;case 8:c=qd(b);a.g=c;break;case 10:c=pd(b);a.l=c;break;case 11:c=J(b);a.u=c;break;case 12:c=J(b);a.s=c;break;case 13:c=N(b);a.m=c;break;case 1E3:c=J(b);a.v=c;break;default:a.b=a.b||[],c=Jd(b,qx),a.b.push(c)}}function ux(a){null===a.a&&(a.a=new pw);return a.a} +rw.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.w();a[0]=b}null!==this.c&&(b=this.c,a[1]=b);null!==this.b&&(b=this.b,a[2]=b);return a};rw.prototype.getExtension=function(){return null};function vx(a,b){for(;G(b);)switch(b.a){case 1:var c=new pw;O(b,c,dx);a.a=c;break;case 2:c=J(b);a.c=c;break;case 3:c=J(b);a.b=c;break;default:H(b)}}function wx(a){null===a.a&&(a.a=new pw);return a.a} +sw.prototype.w=function(){var a=[];null!=this.c&&null==this.h&&(this.h=Gd(this.b,this.c,this.m));if(null!==this.h){var b=this.h;b=Dc(b);a[0]=b}null!=this.s&&null==this.u&&(this.u=Gd(this.b,this.s,this.C));null!==this.u&&(b=this.u,b=Dc(b),a[1]=b);xx(this);null!==this.f&&(b=this.f,b=b.slice(),a[2]=b);null!=this.j&&null==this.l&&(this.l=Fd(Wc.prototype.Ma,this.b,this.j,this.v));null!==this.l&&(b=this.l,b=b.slice(),a[3]=b);yx(this);null!==this.a&&(b=this.a,b=b.slice(),a[4]=b);null!==this.g&&(b=this.g, +a[5]=b);return a};sw.prototype.getExtension=function(){return null};function zx(a,b){for(a.b=jd(b);G(b);)switch(b.a){case 1:null===a.c&&(a.c=b.b);kd(b);a.m=id(b);break;case 2:null===a.s&&(a.s=b.b);kd(b);a.C=id(b);break;case 3:null===a.o&&(a.o=b.b);kd(b);a.B=id(b);break;case 4:null===a.j&&(a.j=b.b);kd(b);a.v=id(b);break;case 5:null===a.i&&(a.i=b.b);kd(b);a.A=id(b);break;case 6:a.g=J(b);break;case 1E3:H(b);break;case 1001:H(b);break;case 1002:H(b);break;default:H(b)}} +function Ax(a){return null!==a.h?Zc(a.h):a.b&&null!=a.c&&null!=a.m?(a=Zc(a.b,a.c,a.m-a.c),a.ca(),a.ca(),a):Zc()}function Bx(a){xx(a);return a.f?a.f.length:0}function Cx(a){xx(a);return a.f}function xx(a){null!=a.o&&null==a.f&&(a.f=Fd(Wc.prototype.Ma,a.b,a.o,a.B))}function Dx(a){yx(a);return a.a?a.a.length:0}function Ex(a){yx(a);return a.a}function yx(a){null!=a.i&&null==a.a&&(a.a=Fd(Wc.prototype.Ma,a.b,a.i,a.A))} +tw.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[0]=b}null!==this.c&&(b=this.c,b=b.w(),a[1]=b);null!==this.g&&(b=this.g,a[2]=b);null!==this.h&&(b=this.h,a[3]=b);null!==this.i&&(b=this.i,a[4]=b);null!==this.j&&(b=this.j,b=Oc(b,!1),a[5]=b);null!==this.l&&(b=this.l,a[6]=b);null!==this.f&&(b=this.f,b=Oc(b,!0),a[7]=b);null!==this.o&&(b=this.o,a[8]=b);null!==this.m&&(b=this.m,a[9]=b);null!==this.s&&(b=this.s,a[999]=b);return a}; +var Fx=[];tw.prototype.getExtension=function(a){var b=!1;25E6<=a&&536870912>a&&(b=!0);return b?Id(this.b,a):null};function Gx(a){a.b=a.b||[];return a.b} +function Hx(a){if(a){if(a.a)for(var b=0;b<a.a.length;b++){var c=a.a[b];c&&(cx(c.a),c.a=null,c.c=null,c.b=null)}a.a=null;if(b=a.c)b.h=null,b.c=null,b.m=null,b.u=null,b.s=null,b.C=null,b.f=null,b.o=null,b.B=null,b.l=null,b.j=null,b.v=null,b.a=null,b.i=null,b.A=null,b.g=null;a.c=null;a.g=null;a.h=null;a.i=null;a.j=null;a.l=null;a.f=null;a.o=null;a.m=null;a.s=null;if(a.b)for(b=0;b<a.b.length;b++)wd(a.b[b]);a.b=null}} +function Ix(a,b){for(;G(b);)switch(b.a){case 1:var c=new rw;O(b,c,vx);a.a=a.a||[];a.a.push(c);break;case 2:c=new sw;O(b,c,zx);a.c=c;break;case 3:c=J(b);a.g=c;break;case 4:c=J(b);a.h=c;break;case 5:c=nd(b);a.i=c;break;case 6:c=pd(b);a.j=c;break;case 7:c=M(b);a.l=c;break;case 8:c=qd(b);a.f=c;break;case 9:c=J(b);a.o=c;break;case 10:c=J(b);a.m=c;break;case 1E3:c=J(b);a.s=c;break;default:a.b=a.b||[],c=Jd(b,Fx),a.b.push(c)}}function Jx(a){null===a.c&&(a.c=new sw);return a.c} +uw.prototype.w=function(){var a=[];Kx(this);if(null!==this.c){var b=this.c;b=Dc(b);a[0]=b}null!==this.j&&(b=this.j,a[1]=b);null!==this.f&&(b=this.f,a[2]=b);null!==this.g&&(b=this.g,a[3]=b);null!==this.h&&(b=this.h,a[4]=b);null!==this.b&&(b=this.b,b=Oc(b,!0),a[5]=b);null!==this.l&&(b=this.l,a[999]=b);return a};var Lx=[];uw.prototype.getExtension=function(a){var b=!1;25E6<=a&&536870912>a&&(b=!0);return b?Id(this.a,a):null}; +function Mx(a){if(a){a.c=null;a.i=null;a.m=null;a.j=null;a.f=null;a.g=null;a.h=null;a.b=null;a.l=null;if(a.a)for(var b=0;b<a.a.length;b++)wd(a.a[b]);a.a=null}}function Nx(a,b){for(a.o=jd(b);G(b);)switch(b.a){case 1:null===a.i&&(a.i=b.b);kd(b);a.m=id(b);break;case 2:var c=M(b);a.j=c;break;case 3:c=J(b);a.f=c;break;case 4:c=J(b);a.g=c;break;case 5:c=nd(b);a.h=c;break;case 6:c=qd(b);a.b=c;break;case 1E3:c=J(b);a.l=c;break;default:a.a=a.a||[],c=Jd(b,Lx),a.a.push(c)}} +uw.prototype.getImageData=function(){Kx(this);return this.c};function Kx(a){null!=a.i&&null==a.c&&(a.c=Gd(a.o,a.i,a.m))} +vw.prototype.w=function(){var a=[];if(null!==this.h){var b=this.h;a[0]=b}if(null!=this.b&&null==this.c){var c=this.j,d=this.b,e=this.i;if(c&&null!=d&&null!=e){b=[];for(c=gd(c,d,e-d);G(c);)b.push(od(c));hd(c)}else b=null;this.c=b}if(null!==this.c){b=this.c;b=b.slice();for(c=0;c<b.length;c++)b[c]=Dc(b[c]);a[1]=b}null!==this.a&&(b=this.a,b=b.w(),a[2]=b);null!==this.f&&(b=this.f,a[3]=b);null!==this.g&&(b=this.g,a[4]=b);return a};vw.prototype.getExtension=function(){return null}; +function Ox(a,b){for(a.j=jd(b);G(b);)switch(b.a){case 1:var c=N(b);a.h=c;break;case 2:null===a.b&&(a.b=b.b);kd(b);a.i=id(b);break;case 3:c=new pw;O(b,c,dx);a.a=c;break;case 4:c=J(b);a.f=c;break;case 5:c=J(b);a.g=c;break;default:H(b)}} +ww.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;b=b.w();a[0]=b}null!==this.g&&(b=this.g,a[1]=b);null!==this.h&&(b=this.h,a[2]=b);null!==this.j&&(b=this.j,a[3]=b);null!==this.c&&(b=this.c,a[4]=b);null!==this.f&&(b=this.f,b=Oc(b,!0),a[5]=b);null!==this.i&&(b=this.i,a[999]=b);return a};var Px=[];ww.prototype.getExtension=function(a){var b=!1;25E6<=a&&536870912>a&&(b=!0);return b?Id(this.a,a):null}; +function Qx(a){if(a){var b=a.b;b&&(b.h=null,b.c=null,b.b=null,b.i=null,cx(b.a),b.a=null,b.f=null,b.g=null);a.b=null;a.g=null;a.h=null;a.j=null;a.c=null;a.f=null;a.i=null;if(a.a)for(b=0;b<a.a.length;b++)wd(a.a[b]);a.a=null}} +function Rx(a,b){for(;G(b);)switch(b.a){case 1:var c=new vw;O(b,c,Ox);a.b=c;break;case 2:c=J(b);a.g=c;break;case 3:c=J(b);a.h=c;break;case 4:c=nd(b);a.j=c;break;case 5:c=M(b);a.c=c;break;case 6:c=qd(b);a.f=c;break;case 1E3:c=J(b);a.i=c;break;default:a.a=a.a||[],c=Jd(b,Px),a.a.push(c)}} +xw.prototype.w=function(){var a=[];if(null!==this.g){var b=this.g;a[0]=b}null!=this.a&&null==this.b&&(this.b=Fd(Wc.prototype.Ce,this.i,this.a,this.h));null!==this.b&&(b=this.b,b=b.slice(),b=Pc(b,!1),a[1]=b);null!==this.f&&(b=this.f,a[2]=b);null!==this.c&&(b=this.c,a[3]=b);return a};xw.prototype.getExtension=function(){return null}; +function Sx(a,b){for(a.i=jd(b);G(b);)switch(b.a){case 1:var c=N(b);a.g=c;break;case 2:null===a.a&&(a.a=b.b);kd(b);a.h=id(b);break;case 3:c=J(b);a.f=c;break;case 4:c=J(b);a.c=c;break;default:H(b)}}yw.prototype.w=function(){var a=[];if(null!==this.f){var b=this.f;a[0]=b}null!==this.g&&(b=this.g,a[1]=b);null!==this.c&&(b=this.c,a[2]=b);null!==this.b&&(b=this.b,a[3]=b);null!==this.a&&(b=this.a,b=Oc(b,!1),a[6]=b);return a};yw.prototype.getExtension=function(){return null}; +function Tx(a){a&&(a.f=null,a.g=null,a.c=null,a.b=null,a.a=null)}function Ux(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.f=c;break;case 2:c=J(b);a.g=c;break;case 3:c=J(b);a.c=c;break;case 4:c=J(b);a.b=c;break;case 7:c=pd(b);a.a=c;break;default:H(b)}}function Vx(a){return null==a.f?0:a.f}function Wx(a){return null==a.g?0:a.g}function Xx(a){return null==a.c?0:a.c}function Yx(a){return null==a.b?0:a.b} +zw.prototype.w=function(){var a=[];Zx(this);if(null!==this.b){var b=this.b;b=Dc(b);a[0]=b}if(null!==this.a){b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[1]=b}return a};zw.prototype.getExtension=function(){return null};function $x(a,b){for(a.g=jd(b);G(b);)switch(b.a){case 1:null===a.c&&(a.c=b.b);kd(b);a.f=id(b);break;case 2:var c=new yw;O(b,c,Ux);a.a=a.a||[];a.a.push(c);break;default:H(b)}}function Zx(a){null!=a.c&&null==a.b&&(a.b=Gd(a.g,a.c,a.f))} +function ay(a,b){return a.a[b]}Aw.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}null!==this.a&&(b=this.a,a[1]=b);return a};Aw.prototype.getExtension=function(){return null};function by(a,b){for(;G(b);)switch(b.a){case 1:var c=N(b);a.b=c;break;case 2:c=N(b);a.a=c;break;default:H(b)}}Bw.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;a[0]=b}null!==this.c&&(b=this.c,a[1]=b);null!==this.b&&(b=this.b,a[2]=b);return a};Bw.prototype.getExtension=function(){return null}; +function cy(a){a&&(a.a=null,a.c=null,a.b=null)}function dy(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.a=c;break;case 2:c=J(b);a.c=c;break;case 3:c=J(b);a.b=c;break;default:H(b)}}Cw.prototype.w=function(){var a=[];if(null!==this.f){var b=this.f;a[0]=b}null!=this.b&&null==this.c&&(this.c=Gd(this.h,this.b,this.g));null!==this.c&&(b=this.c,b=Dc(b),a[1]=b);null!==this.a&&(b=this.a,b=b.slice(),a[2]=b);return a};Cw.prototype.getExtension=function(){return null}; +function ey(a){a&&(a.f=null,a.c=null,a.b=null,a.g=null,a.a=null)}function fy(a,b){for(a.h=jd(b);G(b);)switch(b.a){case 1:var c=L(b);a.f=c;break;case 2:null===a.b&&(a.b=b.b);kd(b);a.g=id(b);break;case 3:c=J(b);a.a=a.a||[];a.a.push(c);break;default:H(b)}}Dw.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[0]=b}return a};Dw.prototype.getExtension=function(){return null}; +function gy(a,b){for(;G(b);)switch(b.a){case 1:var c=new Cw;O(b,c,fy);a.a=a.a||[];a.a.push(c);break;default:H(b)}}Ew.prototype.w=function(){return[]};Ew.prototype.getExtension=function(){return null};function hy(a,b){for(;G(b);)H(b)}Fw.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[0]=b}null!==this.b&&(b=this.b,b=b.w(),a[1]=b);return a};Fw.prototype.getExtension=function(){return null}; +function iy(a,b){for(;G(b);)switch(b.a){case 1:var c=new ow;O(b,c,Rw);a.a=a.a||[];a.a.push(c);break;case 2:c=new Bw;O(b,c,dy);a.b=c;break;default:H(b)}}function jy(a){return null!=a.a?!0:!1}Gw.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[0]=b}null!==this.b&&(b=this.b,b=b.w(),a[1]=b);return a};Gw.prototype.getExtension=function(){return null}; +function ky(a,b){for(;G(b);)switch(b.a){case 1:var c=new qw;O(b,c,tx);a.a=a.a||[];a.a.push(c);break;case 2:c=new Bw;O(b,c,dy);a.b=c;break;default:H(b)}}function ly(a){return null!=a.a?!0:!1}Hw.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[0]=b}null!==this.b&&(b=this.b,b=b.w(),a[1]=b);return a};Hw.prototype.getExtension=function(){return null}; +function my(a,b){for(;G(b);)switch(b.a){case 1:var c=new tw;O(b,c,Ix);a.a=a.a||[];a.a.push(c);break;case 2:c=new Bw;O(b,c,dy);a.b=c;break;default:H(b)}}function ny(a){return null!=a.a?!0:!1}Iw.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[0]=b}null!==this.b&&(b=this.b,b=b.w(),a[1]=b);return a};Iw.prototype.getExtension=function(){return null}; +function oy(a,b){for(;G(b);)switch(b.a){case 1:var c=new Xt;O(b,c,Bu);a.a=a.a||[];a.a.push(c);break;case 2:c=new Bw;O(b,c,dy);a.b=c;break;default:H(b)}}function py(a){return null!=a.a?!0:!1}Jw.prototype.w=function(){var a=[];if(null!==this.Aa){var b=this.Aa;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[0]=b}return a};Jw.prototype.getExtension=function(){return null};function qy(a,b){for(;G(b);)switch(b.a){case 1:var c=new uw;O(b,c,Nx);a.Aa=a.Aa||[];a.Aa.push(c);break;default:H(b)}} +function ry(a){return null!=a.Aa?!0:!1}Kw.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[0]=b}null!==this.b&&(b=this.b,b=b.w(),a[1]=b);return a};Kw.prototype.getExtension=function(){return null};function sy(a,b){for(;G(b);)switch(b.a){case 1:var c=new ww;O(b,c,Rx);a.a=a.a||[];a.a.push(c);break;case 2:c=new Bw;O(b,c,dy);a.b=c;break;default:H(b)}} +Lw.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}null!==this.a&&(b=this.a,a[1]=b);return a};Lw.prototype.getExtension=function(){return null};function ty(a,b){for(;G(b);)switch(b.a){case 1:var c=L(b);a.b=c;break;case 2:c=J(b);a.a=c;break;default:H(b)}} +function uy(a,b){for(;G(b);)switch(b.a){case 1:var c=new mw;O(b,c,nw);a.c=c;break;case 2:c=new Aw;O(b,c,by);a.u=c;break;case 3:c=new Hu;O(b,c,av);a.b=a.b||[];a.b.push(c);break;case 4:c=new zw;O(b,c,$x);a.h=c;break;case 5:c=new xw;O(b,c,Sx);a.f=a.f||[];a.f.push(c);break;case 6:c=new Ew;O(b,c,hy);a.C=c;break;case 7:c=new Fw;O(b,c,iy);a.o=c;break;case 8:c=new Gw;O(b,c,ky);a.j=c;break;case 9:c=new Hw;O(b,c,my);a.i=c;break;case 10:c=new Iw;O(b,c,oy);a.l=c;break;case 11:c=new Jw;O(b,c,qy);a.a=c;break;case 12:c= +new Kw;O(b,c,sy);a.A=c;break;case 13:c=new Dw;O(b,c,gy);a.v=c;break;case 14:c=J(b);a.B=c;break;case 15:c=new Lw;O(b,c,ty);a.m=a.m||[];a.m.push(c);break;case 16:c=M(b);a.s=c;break;default:a.g=a.g||[],c=Jd(b,vy),a.g.push(c)}} +Mw.prototype.w=function(){var a=[];if(null!==this.c){var b=this.c;b=b.w();a[0]=b}null!==this.u&&(b=this.u,b=b.w(),a[1]=b);if(null!==this.b){b=this.b;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[2]=b}null!==this.h&&(b=this.h,b=b.w(),a[3]=b);if(null!==this.f){b=this.f;b=b.slice();for(c=0;c<b.length;c++)b[c]=b[c].w();a[4]=b}null!==this.C&&(b=this.C,b=b.w(),a[5]=b);null!==this.o&&(b=this.o,b=b.w(),a[6]=b);null!==this.j&&(b=this.j,b=b.w(),a[7]=b);null!==this.i&&(b=this.i,b=b.w(),a[8]=b);null!== +this.l&&(b=this.l,b=b.w(),a[9]=b);null!==this.a&&(b=this.a,b=b.w(),a[10]=b);null!==this.A&&(b=this.A,b=b.w(),a[11]=b);null!==this.v&&(b=this.v,b=b.w(),a[12]=b);null!==this.B&&(b=this.B,a[13]=b);if(null!==this.m){b=this.m;b=b.slice();for(c=0;c<b.length;c++)b[c]=b[c].w();a[14]=b}null!==this.s&&(b=this.s,a[15]=b);return a};var vy=[];Mw.prototype.getExtension=function(a){var b=!1;25E6<=a&&536870912>a&&(b=!0);return b?Id(this.g,a):null}; +function wy(a){a.g=a.g||[];a=a.g;var b=vy,c=Id(a,96629873);if(c)a=c;else{c=null;if(b)for(var d=0;d<b.length;d++)if(96629873==b[d].c){c=b[d];break}if(c&&11==c.b&&null!=c.a){c=c.a();b:{var e=null;if(b)for(d=0;d<b.length;d++)if(96629873==b[d].c){e=b[d];break}if(e){b=vd(96629873,c,null,null,null,e);for(d=0;d<a.length;d++)if((e=a[d])&&96629873==e.c){a[d]=b;break b}a.push(b)}}a=c}else a=null}return a}function Ay(a){null===a.c&&(a.c=new mw);return a.c}function By(a){null===a.c&&(a.c=new mw);return a.c} +function Cy(a){null===a.u&&(a.u=new Aw);return a.u}function Dy(a){null===a.h&&(a.h=new zw);return a.h}function Ey(a){return null!=a.o?!0:!1}function Fy(a){null===a.o&&(a.o=new Fw);return a.o}function Gy(a){return null!=a.j?!0:!1}function Hy(a){null===a.j&&(a.j=new Gw);return a.j}function Iy(a){null===a.i&&(a.i=new Hw);return a.i}function Jy(a){return null!=a.l?!0:!1}function Ky(a){null===a.l&&(a.l=new Iw);return a.l}function Ly(a){null===a.a&&(a.a=new Jw);return a.a};function My(){this.b=this.a=null}function Ny(){this.b=this.a=null}My.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.w();a[1]=b}null!==this.b&&(b=this.b,a[2]=b);return a};My.prototype.getExtension=function(){return null};Ny.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=Oc(b,!1);a[0]=b}null!==this.b&&(b=this.b,b=Oc(b,!1),a[1]=b);return a};Ny.prototype.getExtension=function(){return null}; +function Oy(a,b){for(;G(b);)switch(b.a){case 1:var c=pd(b);a.a=c;break;case 2:c=pd(b);a.b=c;break;default:H(b)}};function Py(){this.a=this.f=this.b=this.g=this.c=null}Py.prototype.w=function(){var a=[];if(null!==this.c){var b=this.c;a[0]=b}null!==this.g&&(b=this.g,b=Oc(b,!1),a[1]=b);null!==this.b&&(b=this.b,a[2]=b);null!==this.f&&(b=this.f,a[3]=b);null!==this.a&&(b=this.a,a[4]=b);return a};Py.prototype.getExtension=function(){return null};function Qy(){this.c=this.b=this.a=null}Qy.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;a[0]=b}null!==this.b&&(b=this.b,a[1]=b);null!==this.c&&(b=this.c,a[2]=b);return a};Qy.prototype.getExtension=function(){return null};function Ry(){this.a=this.f=this.h=this.c=this.b=this.g=null}Ry.prototype.w=function(){var a=[];if(null!==this.g){var b=this.g;b=Oc(b,!1);a[0]=b}null!==this.b&&(b=this.b,a[1]=b);null!==this.c&&(b=this.c,a[2]=b);null!==this.h&&(b=this.h,a[3]=b);null!==this.f&&(b=this.f,a[4]=b);null!==this.a&&(b=this.a,b=b.slice(),a[5]=b);return a};Ry.prototype.getExtension=function(){return null};function Sy(){this.b=this.a=null}function Ty(){}Sy.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.w();a[0]=b}null!==this.b&&(b=this.b,b=b.w(),a[2]=b);return a};Sy.prototype.getExtension=function(){return null};Ty.prototype.w=function(){return[]};Ty.prototype.getExtension=function(){return null};function Uy(a,b){for(;G(b);)H(b)};function Vy(){this.a=null}function Wy(){this.c=this.a=this.b=null}function Xy(){this.b=this.a=null}function Yy(){this.b=this.a=null}function Zy(){this.c=this.i=this.j=this.h=this.g=this.f=this.b=this.a=null}function $y(){this.f=this.g=this.c=this.a=this.b=null}function az(){this.b=this.a=null}Vy.prototype.w=function(){var a=[];null!==this.a&&(a[0]=this.a);return a};Vy.prototype.getExtension=function(){return null}; +Wy.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}null!==this.a&&(b=this.a,b=b.w(),a[1]=b);null!==this.c&&(b=this.c,a[2]=b);return a};Wy.prototype.getExtension=function(){return null};Xy.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;a[0]=b}null!==this.b&&(b=this.b,a[1]=b);return a};Xy.prototype.getExtension=function(){return null};Yy.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;a[0]=b}null!==this.b&&(b=this.b,a[1]=b);return a}; +Yy.prototype.getExtension=function(){return null};function bz(a){if(null===a)a=null;else{var b=new Yy;b.a=null;b.b=null;b.a=a.a;b.b=a.b;a=b}return a}function cz(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.a=c;break;case 2:c=J(b);a.b=c;break;default:H(b)}}function dz(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a||a.b!==b.b?!1:!0} +Zy.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[0]=b}null!==this.b&&(b=this.b,b=b.w(),a[1]=b);null!==this.f&&(b=this.f,a[2]=b);null!==this.g&&(b=this.g,a[4]=b);null!==this.h&&(b=this.h,a[5]=b);null!==this.j&&(b=this.j,a[6]=b);null!==this.i&&(b=this.i,a[8]=b);null!==this.c&&(b=this.c,a[9]=b);return a};Zy.prototype.getExtension=function(){return null};function ez(){return new Zy} +function fz(a){if(null===a)a=null;else{var b=new Zy;if(b.a)for(var c=0;c<b.a.length;c++){var d=b.a[c];d&&(d.a=null,d.b=null)}b.a=null;(c=b.b)&&Wk(c);b.b=null;b.f=null;b.g=null;b.h=null;b.j=null;b.i=null;b.c=null;b.a=Bd(a.a,bz);b.b=a.b?Vk(a.b):null;b.f=a.f;b.g=a.g;b.h=a.h;b.j=a.j;b.i=a.i;b.c=a.c;a=b}return a}function gz(){} +function hz(a,b){for(;G(b);)switch(b.a){case 1:var c=new Yy;O(b,c,cz);a.a=a.a||[];a.a.push(c);break;case 2:c=new Sk;O(b,c,Xk);a.b=c;break;case 3:c=J(b);a.f=c;break;case 5:c=J(b);a.g=c;break;case 6:c=J(b);a.h=c;break;case 7:c=J(b);a.j=c;break;case 9:c=N(b);a.i=c;break;case 10:c=N(b);a.c=c;break;default:H(b)}}function iz(a,b){return a===b?!0:null===a||null===b?!1:Dd(a.a,b.a,dz)&&Zk(a.b,b.b)&&a.f===b.f&&a.g===b.g&&a.h===b.h&&a.j===b.j&&a.i===b.i&&a.c===b.c?!0:!1} +$y.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}null!==this.a&&(b=this.a,b=b.w(),a[1]=b);null!==this.c&&(b=this.c,a[2]=b);null!==this.g&&(b=this.g,a[3]=b);null!==this.f&&(b=this.f,a[4]=b);return a};$y.prototype.getExtension=function(){return null};az.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;a[0]=b}null!==this.b&&(b=this.b,a[1]=b);return a};az.prototype.getExtension=function(){return null};function jz(){this.a=this.b=this.c=null}function kz(){this.a=null}function lz(){this.a=null}jz.prototype.w=function(){var a=[];if(null!==this.c){var b=this.c;b=b.w();a[0]=b}null!==this.b&&(b=this.b,b=b.w(),a[1]=b);null!==this.a&&(b=this.a,b=b.w(),a[3]=b);return a};jz.prototype.getExtension=function(){return null};function mz(){return new jz} +function nz(a){if(null===a)var b=null;else{b=new jz;var c=b.c;c&&cj(c);b.c=null;if(c=b.b)c.a=null;b.b=null;if(c=b.a)c.a=null;b.a=null;b.c=a.c?bj(a.c):null;if(a.b){c=a.b;var d=new kz;d.a=null;d.a=c.a;c=d}else c=null;b.b=c;a.a?(a=a.a,c=new lz,c.a=null,c.a=a.a,a=c):a=null;b.a=a}return b}function oz(){}function pz(a,b){for(;G(b);)switch(b.a){case 1:var c=new $i;O(b,c,dj);a.c=c;break;case 2:c=new kz;O(b,c,qz);a.b=c;break;case 4:c=new lz;O(b,c,rz);a.a=c;break;default:H(b)}} +function sz(a,b){if(a===b)b=!0;else if(null===a||null===b)b=!1;else{var c;if(c=ej(a.c,b.c)){c=a.b;var d=b.b;c=c===d?!0:null===c||null===d?!1:c.a!==d.a?!1:!0}c&&(a=a.a,b=b.a,c=a===b?!0:null===a||null===b?!1:a.a!==b.a?!1:!0);b=c?!0:!1}return b}kz.prototype.w=function(){var a=[];null!==this.a&&(a[0]=this.a);return a};kz.prototype.getExtension=function(){return null};function qz(a,b){for(;G(b);)switch(b.a){case 1:a.a=N(b);break;default:H(b)}} +lz.prototype.w=function(){var a=[];null!==this.a&&(a[0]=this.a);return a};lz.prototype.getExtension=function(){return null};function rz(a,b){for(;G(b);)switch(b.a){case 1:a.a=L(b);break;default:H(b)}};function tz(){this.a=this.h=this.b=this.c=this.g=this.f=null}tz.prototype.w=function(){var a=[];if(null!==this.f){var b=this.f;a[0]=b}null!==this.g&&(b=this.g,a[1]=b);null!==this.c&&(b=this.c,a[2]=b);null!==this.b&&(b=this.b,a[3]=b);null!==this.h&&(b=this.h,a[4]=b);null!==this.a&&(b=this.a,a[5]=b);return a};tz.prototype.getExtension=function(){return null};function uz(){this.a=null}uz.prototype.w=function(){var a=[];null!==this.a&&(a[0]=this.a);return a};uz.prototype.getExtension=function(){return null};function vz(a,b){for(;G(b);)switch(b.a){case 1:a.a=N(b);break;default:H(b)}};function wz(){this.l=this.s=this.g=this.o=this.f=this.b=this.j=this.i=this.h=this.c=this.a=this.m=null} +wz.prototype.w=function(){var a=[];if(null!==this.m){var b=this.m;a[0]=b}null!==this.a&&(b=this.a,b=b.slice(),a[1]=b);null!==this.c&&(b=this.c,b=b.slice(),a[2]=b);null!==this.h&&(b=this.h,b=b.w(),a[3]=b);null!==this.i&&(b=this.i,a[4]=b);null!==this.j&&(b=this.j,a[5]=b);null!==this.b&&(b=this.b,b=b.slice(),a[6]=b);null!==this.f&&(b=this.f,b=b.slice(),a[7]=b);null!==this.o&&(b=this.o,a[8]=b);null!==this.g&&(b=this.g,b=b.w(),a[9]=b);null!==this.s&&(b=this.s,a[10]=b);null!==this.l&&(b=this.l,a[11]=b); +return a};function xz(a){a.m=null;a.a=null;a.c=null;var b=a.h;b&&Mi(b);a.h=null;a.i=null;a.j=null;a.b=null;a.f=null;a.o=null;if(b=a.g)b.a=null;a.g=null;a.s=null;a.l=null}wz.prototype.getExtension=function(){return null}; +function yz(a,b){for(;G(b);)switch(b.a){case 1:var c=L(b);a.m=c;break;case 2:c=N(b);a.a=a.a||[];a.a.push(c);break;case 3:c=N(b);a.c=a.c||[];a.c.push(c);break;case 4:c=new Ki;O(b,c,Ni);a.h=c;break;case 5:c=N(b);a.i=c;break;case 6:c=N(b);a.j=c;break;case 7:c=J(b);a.b=a.b||[];a.b.push(c);break;case 8:c=N(b);a.f=a.f||[];a.f.push(c);break;case 9:c=K(b);a.o=c;break;case 10:c=new uz;O(b,c,vz);a.g=c;break;case 11:c=N(b);a.s=c;break;case 12:c=J(b);a.l=c;break;default:H(b)}} +wz.prototype.Gb=function(a){this.i=a};function zz(){this.a=null}zz.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.w();a[0]=b}return a};zz.prototype.getExtension=function(){return null};function Az(){return new zz} +function Bz(a){if(null===a)var b=null;else{b=new zz;var c=b.a;c&&xz(c);b.a=null;if(a.a){c=new wz;a=a.a;xz(c);c.m=a.m;c.a=Ad(a.a);c.c=Ad(a.c);c.h=a.h?Li(a.h):null;c.i=a.i;c.j=a.j;c.b=Ad(a.b);c.f=Ad(a.f);c.o=a.o;if(a.g){var d=new uz;var e=a.g;d.a=null;d.a=e.a}else d=null;c.g=d;c.s=a.s;c.l=a.l}else c=null;b.a=c}return b}function Cz(){}function Dz(a,b){for(;G(b);)switch(b.a){case 1:var c=new wz;O(b,c,yz);a.a=c;break;default:H(b)}} +function Ez(a,b){if(a===b)a=!0;else if(null===a||null===b)a=!1;else{a=a.a;b=b.a;var c;if(!(c=a===b)){if(null===a||null===b)a=0;else{if(c=a.m===b.m&&Cd(a.a,b.a)&&Cd(a.c,b.c)&&Oi(a.h,b.h)&&a.i===b.i&&a.j===b.j&&Cd(a.b,b.b)&&Cd(a.f,b.f)&&a.o===b.o){c=a.g;var d=b.g;c=c===d?!0:null===c||null===d?!1:c.a!==d.a?!1:!0}a=c&&a.s===b.s&&a.l===b.l}c=a}a=c?!0:!1}return a};function Fz(){this.a=null}Fz.prototype.w=function(){var a=[];null!==this.a&&(a[0]=this.a);return a};Fz.prototype.getExtension=function(){return null};function Gz(){this.a=null}Gz.prototype.w=function(){var a=[];null!==this.a&&(a[0]=this.a);return a};Gz.prototype.getExtension=function(){return null};function Hz(){this.j=this.a=this.c=this.b=this.i=this.h=this.f=this.g=null}function Iz(){this.a=null}Hz.prototype.w=function(){var a=[];if(null!==this.g){var b=this.g;a[0]=b}null!==this.f&&(b=this.f,a[1]=b);null!==this.h&&(b=this.h,b=Oc(b,!1),a[2]=b);null!==this.i&&(b=this.i,b=Oc(b,!1),a[3]=b);null!==this.b&&(b=this.b,a[4]=b);null!==this.c&&(b=this.c,a[5]=b);null!==this.a&&(b=this.a,a[6]=b);null!==this.j&&(b=this.j,a[7]=b);return a};Hz.prototype.getExtension=function(){return null}; +function Jz(){return new Hz}function Kz(a){if(null===a)a=null;else{var b=new Hz;b.g=null;b.f=null;b.h=null;b.i=null;b.b=null;b.c=null;b.a=null;b.j=null;b.g=a.g;b.f=a.f;b.h=a.h;b.i=a.i;b.b=a.b;b.c=a.c;b.a=a.a;b.j=a.j;a=b}return a}function Lz(){} +function Mz(a,b){for(;G(b);)switch(b.a){case 1:var c=L(b);a.g=c;break;case 2:c=L(b);a.f=c;break;case 3:c=pd(b);a.h=c;break;case 4:c=pd(b);a.i=c;break;case 5:c=L(b);a.b=c;break;case 6:c=K(b);a.c=c;break;case 7:c=K(b);a.a=c;break;case 8:c=K(b);a.j=c;break;default:H(b)}}function Nz(a,b){return a===b?!0:null===a||null===b?!1:a.g!==b.g||a.f!==b.f||a.h!==b.h||a.i!==b.i||a.b!==b.b||a.c!==b.c||a.a!==b.a||a.j!==b.j?!1:!0}Iz.prototype.w=function(){var a=[];null!==this.a&&(a[0]=this.a);return a}; +Iz.prototype.getExtension=function(){return null};yd(qx,53863091,11,Jz,Lz,Mz,Kz,Nz);yd(qx,32819068,11,ut,At,Bt,vt,Et);yd(qx,42466818,11,Ht,Kt,Lt,It,Nt);yd(qx,52617685,11,function(){return new st},function(){},Qt,function(a){return null===a?null:zt(a)},Gt);yd(qx,40154408,11,Az,Cz,Dz,Bz,Ez);yd(qx,30096869,11,mz,oz,pz,nz,sz);yd(qx,51650189,11,ft,jt,kt,gt,mt); +yd(qx,177034656,11,function(){return new Iz},function(){},function(a,b){for(;G(b);)switch(b.a){case 1:a.a=K(b);break;default:H(b)}},function(a){if(null===a)a=null;else{var b=new Iz;b.a=null;b.a=a.a;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a?!1:!0});yd(Ow,28517612,11,ez,gz,hz,fz,iz); +yd(Ow,48343962,11,function(){return new $y},function(){},function(a,b){for(;G(b);)switch(b.a){case 1:var c=K(b);a.b=c;break;case 2:c=new Sk;O(b,c,Xk);a.a=c;break;case 3:c=L(b);a.c=c;break;case 4:c=L(b);a.g=c;break;case 5:c=L(b);a.f=c;break;default:H(b)}},function(a){if(null===a)a=null;else{var b=new $y;b.b=null;var c=b.a;c&&Wk(c);b.a=null;b.c=null;b.g=null;b.f=null;b.b=a.b;b.a=a.a?Vk(a.a):null;b.c=a.c;b.g=a.g;b.f=a.f;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.b===b.b&&Zk(a.a, +b.a)&&a.c===b.c&&a.g===b.g&&a.f===b.f?!0:!1});yd(Ow,49095464,11,function(){return new az},function(){},function(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.a=c;break;case 2:c=J(b);a.b=c;break;default:H(b)}},function(a){if(null===a)a=null;else{var b=new az;b.a=null;b.b=null;b.a=a.a;b.b=a.b;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a||a.b!==b.b?!1:!0});yd(Ow,30096869,11,mz,oz,pz,nz,sz); +yd(Ow,132080860,11,function(){return new Fz},function(){},function(a,b){for(;G(b);)switch(b.a){case 1:a.a=L(b);break;default:H(b)}},function(a){if(null===a)a=null;else{var b=new Fz;b.a=null;b.a=a.a;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a?!1:!0});yd(Ow,51650189,11,ft,jt,kt,gt,mt);yd(Ow,53863091,11,Jz,Lz,Mz,Kz,Nz); +yd(yu,30929027,11,function(){return new Vy},function(){},function(a,b){for(;G(b);)switch(b.a){case 1:a.a=J(b);break;default:H(b)}},function(a){if(null===a)a=null;else{var b=new Vy;b.a=null;b.a=a.a;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a?!1:!0}); +yd(yu,66786615,11,function(){return new Wy},function(){},function(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.b=c;break;case 2:c=new wi;O(b,c,Bi);a.a=c;break;case 3:c=J(b);a.c=c;break;default:H(b)}},function(a){if(null===a)a=null;else{var b=new Wy;b.b=null;var c=b.a;c&&Ai(c);b.a=null;b.c=null;b.b=a.b;b.a=a.a?zi(a.a):null;b.c=a.c;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.b===b.b&&Ci(a.a,b.a)&&a.c===b.c?!0:!1});yd(yu,28517612,11,ez,gz,hz,fz,iz); +yd(yu,30511227,11,function(){return new Sy},function(){},function(a,b){for(;G(b);)switch(b.a){case 1:var c=new Ki;O(b,c,Ni);a.a=c;break;case 3:c=new Ty;O(b,c,Uy);a.b=c;break;default:H(b)}},function(a){if(null===a)a=null;else{var b=new Sy,c=b.a;c&&Mi(c);b.a=null;b.b=null;b.a=a.a?Li(a.a):null;b.b=a.b?new Ty:null;a=b}return a},function(a,b){if(a===b)b=!0;else if(null===a||null===b)b=!1;else{var c;if(c=Oi(a.a,b.a))a=a.b,b=b.b,c=a===b?!0:null===a||null===b?!1:!0;b=c?!0:!1}return b}); +yd(yu,30096869,11,mz,oz,pz,nz,sz); +yd(yu,172661375,11,function(){return new tz},function(){},function(a,b){for(;G(b);)switch(b.a){case 1:var c=L(b);a.f=c;break;case 2:c=L(b);a.g=c;break;case 3:c=L(b);a.c=c;break;case 4:c=M(b);a.b=c;break;case 5:c=M(b);a.h=c;break;case 6:c=K(b);a.a=c;break;default:H(b)}},function(a){if(null===a)a=null;else{var b=new tz;b.f=null;b.g=null;b.c=null;b.b=null;b.h=null;b.a=null;b.f=a.f;b.g=a.g;b.c=a.c;b.b=a.b;b.h=a.h;b.a=a.a;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.f!==b.f||a.g!== +b.g||a.c!==b.c||a.b!==b.b||a.h!==b.h||a.a!==b.a?!1:!0});yd(yu,33356690,11,function(){return new Gz},function(){},function(a,b){for(;G(b);)switch(b.a){case 1:a.a=N(b);break;default:H(b)}},function(a){if(null===a)a=null;else{var b=new Gz;b.a=null;b.a=a.a;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a?!1:!0}); +yd(yu,40251317,11,function(){return new Xy},function(){},function(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.a=c;break;case 2:c=J(b);a.b=c;break;default:H(b)}},function(a){if(null===a)a=null;else{var b=new Xy;b.a=null;b.b=null;b.a=a.a;b.b=a.b;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a||a.b!==b.b?!1:!0}); +yd(yu,43229016,11,function(){return new Ry},function(){},function(a,b){for(;G(b);)switch(b.a){case 1:var c=pd(b);a.g=c;break;case 2:c=L(b);a.b=c;break;case 3:c=L(b);a.c=c;break;case 4:c=J(b);a.h=c;break;case 5:c=L(b);a.f=c;break;case 6:c=L(b);a.a=a.a||[];a.a.push(c);break;default:H(b)}},function(a){if(null===a)a=null;else{var b=new Ry;b.g=null;b.b=null;b.c=null;b.h=null;b.f=null;b.a=null;b.g=a.g;b.b=a.b;b.c=a.c;b.h=a.h;b.f=a.f;b.a=Ad(a.a);a=b}return a},function(a,b){return a===b?!0:null===a||null=== +b?!1:a.g===b.g&&a.b===b.b&&a.c===b.c&&a.h===b.h&&a.f===b.f&&Cd(a.a,b.a)?!0:!1});yd(yu,51650189,11,ft,jt,kt,gt,mt);yd(yu,40154408,11,Az,Cz,Dz,Bz,Ez); +yd(yu,60681369,11,function(){return new Qy},function(){},function(a,b){for(;G(b);)switch(b.a){case 1:var c=L(b);a.a=c;break;case 2:c=L(b);a.b=c;break;case 3:c=L(b);a.c=c;break;default:H(b)}},function(a){if(null===a)a=null;else{var b=new Qy;b.a=null;b.b=null;b.c=null;b.a=a.a;b.b=a.b;b.c=a.c;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a||a.b!==b.b||a.c!==b.c?!1:!0}); +yd(yu,135491995,11,function(){return new Py},function(){},function(a,b){for(;G(b);)switch(b.a){case 1:var c=L(b);a.c=c;break;case 2:c=qd(b);a.g=c;break;case 3:c=L(b);a.b=c;break;case 4:c=K(b);a.f=c;break;case 5:c=L(b);a.a=c;break;default:H(b)}},function(a){if(null===a)a=null;else{var b=new Py;b.c=null;b.g=null;b.b=null;b.f=null;b.a=null;b.c=a.c;b.g=a.g;b.b=a.b;b.f=a.f;b.a=a.a;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.c!==b.c||a.g!==b.g||a.b!==b.b||a.f!==b.f||a.a!==b.a?!1: +!0}); +yd(yu,137907910,11,function(){return new My},function(){},function(a,b){for(;G(b);)switch(b.a){case 2:var c=new Ny;O(b,c,Oy);a.a=c;break;case 3:c=N(b);a.b=c;break;default:H(b)}},function(a){if(null===a)a=null;else{var b=new My,c=b.a;c&&(c.a=null,c.b=null);b.a=null;b.b=null;if(a.a){c=a.a;var d=new Ny;d.a=null;d.b=null;d.a=c.a;d.b=c.b;c=d}else c=null;b.a=c;b.b=a.b;a=b}return a},function(a,b){if(a===b)a=!0;else if(null===a||null===b)a=!1;else{var c=a.a,d=b.a;a=c!==d&&(null===c||null===d||c.a!==d.a|| +c.b!==d.b)||a.b!==b.b?!1:!0}return a});yd(yu,53863091,11,Jz,Lz,Mz,Kz,Nz);yd(yu,42466818,11,Ht,Kt,Lt,It,Nt);yd(Fx,53863091,11,Jz,Lz,Mz,Kz,Nz);yd(Fx,85448653,11,ut,At,Bt,vt,Et);yd(qx,69077470,8);yd(Fx,36512758,8);function Oz(a){this.data=a||[]}var Pz;F(Oz,W);function Qz(){Pz||(Pz={a:-1,F:[]},Pz.F=[,be,be,be,ae(256)]);return Pz}Oz.prototype.getZoom=function(){return X(this,0)};function Rz(){this.b=new Uint8Array(840);this.c=0;this.j=this.s=this.l=this.D=!1;this.B=null;this.C=0;this.u=this.A=this.v=this.m=null;this.o=0;this.i=this.h=this.g=this.a=this.f=null}var Sz={Zd:0,$d:4,Tc:8,nd:10,Tf:12};Rz.prototype.G=function(){return this.B};function Tz(a,b){return a[b]%128*4+a[b+1]/64}function Uz(a,b){return(a.b[b+0]<<16|a.b[b+1]<<8|a.b[b+2]|a.b[b+3]<<24)>>>0} +function Vz(a,b,c,d){var e=a.b[c+3];0==a.b[b+3]?d=1:0==e&&(d=0);e=0|$n(a.b[b],a.b[c],d)<<16;e|=$n(a.b[b+1],a.b[c+1],d)<<8;e|=$n(a.b[b+2],a.b[c+2],d);e|=$n(a.b[b+3],a.b[c+3],d)<<24;return e>>>0}function Wz(a,b){a=a[b];128<a&&(a=-(a-128));return a/8}function Xz(a,b){if(0<a.o)return!1;for(var c=0;c<a.c;c++)if(0!=Yz(a,c,b)||null!=Zz(a,c,b))return!1;return!0}function $z(a){return 0==a.c&&!a.C&&!a.D&&!a.l&&!a.s&&!a.j&&!a.o} +function aA(a,b){var c=Math.floor(b);if(bA(a,c))return aA(cA,b);if(c==b)return Uz(a,36*c+12);var d=Math.ceil(b);return Vz(a,36*c+12,36*d+12,(b-c)/(d-c))}function dA(a,b){var c=Math.floor(b);if(bA(a,c))return 0;if(c==b)return Uz(a,36*c+16);var d=Math.ceil(b);return Vz(a,36*c+16,36*d+16,(b-c)/(d-c))}function eA(a,b){var c=Math.floor(b);if(bA(a,c))return 0;if(c==b)return Uz(a,36*c+20);var d=Math.ceil(b);return Vz(a,36*c+20,36*d+20,(b-c)/(d-c))} +function fA(a,b){return a.m&&a.m[b]&&!bA(a,b)?a.m[b]:null}function gA(a,b){if(!a.a||!a.a[b])return 0;a=dw(a.a[b]);return null==a.a?0:a.a}function hA(a,b){if(!a.a||!a.a[b])return 0;a=dw(a.a[b]);return null==a.b?0:a.b}function iA(a,b){if(!a.a||!a.a[b])return 0;a=dw(a.a[b]);return(null==a.g?0:a.g)/1E3}function jA(a,b){if(!a.a||!a.a[b])return 0;a=a.a[b];return null!=a.a&&(a=ew(a),null!=a.c)?null==a.c?0:a.c:0}function kA(a,b){return a.a&&a.a[b]&&null!=a.a[b].l?!0:!1} +function lA(a,b){if(!a.a||!a.a[b])return 0;a=a.a[b];return null!=a.a&&(a=ew(a),null!=a.f)?null==a.f?0:a.f:0}function mA(a,b){var c=nA;if(!a.a||!a.a[b])return null;a=a.a[b];return null!=a.a?(a=ew(a),c.width=null==a.h?0:a.h,c.height=null==a.i?0:a.i,c):null} +function oA(a,b){if(a.f){if(a.f[b])return a=a.f[b],null==a.g?0:a.g}else if(a.a){if(a.a[b])return a=a.a[b],null==a.m?0:a.m}else if(a.g){if(a.g[b])return a=a.g[b],null==a.h?0:a.h}else if(a.h){if(a.h[b])return a=a.h[b],null==a.b?-1:a.b}else if(a.i&&a.i[b])return a=a.i[b],null==a.f?0:a.f;return 0} +function bA(a,b){if(a.f){if(a.f[b]){var c=a.f[b];if(c=null==c.c?!1:c.c)a=a.f[b],c=null==a.h?!1:a.h;return c}}else if(a.a){if(a.a[b])return a=a.a[b],null==a.h?!1:a.h}else if(a.g){if(a.g[b])return a=a.g[b],null==a.g?!1:a.g}else if(a.h){if(a.h[b])return a=a.h[b],null==a.a?!1:a.a}else if(a.i&&a.i[b])return a=a.i[b],null==a.c?!1:a.c;return!1} +function pA(a,b,c){for(var d=0;12>d;d++)c[d]=a.b[d];d=Math.floor(b);if(bA(a,d))for(b=12,d=0;36>d;d++)c[12+d]=cA.b[b+d];else if(b==d)for(b=12+36*b,d=0;36>d;d++)c[12+d]=a.b[b+d];else{var e=Math.ceil(b),f=qA(a,d);a=qA(a,e);c=c.subarray(12);rA(f,a,c,(b-d)/(e-d),sA(d,e,b))}}function qA(a,b){b=12+36*b;return a.b.subarray(b,b+36)}function tA(a,b,c){var d=Math.floor(c);if(bA(a,d))return 0;if(d==c)return Uz(a,36*c+24+12*b+0);var e=Math.ceil(c);return Vz(a,36*d+24+12*b+0,36*e+24+12*b+0,(c-d)/(e-d))} +function uA(a,b,c){var d=Math.floor(c);if(bA(a,d))return 0;var e=Tz(a.b,36*d+24+12*b+4);if(d==c)return e;var f=Math.ceil(c);a=Tz(a.b,36*f+24+12*b+4);return a==e?e:$n(e,a,sA(d,f,c))}function Yz(a,b,c){var d=Math.floor(c),e=Wz(a.b,36*d+24+12*b+10);if(d==c)return e;var f=Math.ceil(c);a=Wz(a.b,36*f+24+12*b+10);return a==e?e:$n(e,a,sA(d,f,c))}function Zz(a,b,c){c=Math.ceil(c);c=36*c+24+12*b+8;b=a.b[c+0]/2;a=a.b[c+1]/2;return 0==b&&0==a?null:[b,a]}function vA(a,b,c){return a?(a=a[b])&&a[c]||null:null} +function wA(a,b){if(a==b)return!0;if(!a||!b||a.length!=b.length)return!1;for(var c=0;c<a.length;c++)if(!xA(a[c],b[c]))return!1;return!0}function xA(a,b){if(a==b)return!0;if(!a||!b||a.length!=b.length)return!1;for(var c=0;c<a.length;c++){var d=a[c],e=b[c];if(!(d===e||d&&e&&d.a==e.a&&d.b==e.b))return!1}return!0} +function yA(a,b){if(a===b)return!0;if(null==a||null==b||a.c!=b.c||a.D!=b.D||a.l!=b.l||a.s!=b.s||a.j!=b.j)return!1;if(a.C&&b.C){if(!xA(a.m,b.m))return!1}else if(a.C||b.C)return!1;if(a.o&&b.o){if(!wA(a.v,b.v)||!wA(a.A,b.A)||!wA(a.u,b.u))return!1}else if(a.o||b.o)return!1;for(var c=0;840>c;++c)if(a.b[c]!=b.b[c])return!1;return!0}function zA(){this.style=new Rz}function AA(a){var b=null;if(a){b=[];for(var c=0;c<a.length;c++)a[c]&&(b[c]=Va(a[c]))}return b}function BA(a,b){a.style.c>b||(a.style.c=b)} +function CA(a,b,c){if(!a.style.m)if(c)a.style.m=[];else return;a.style.m[b]&&a.style.C--;(a.style.m[b]=c)&&a.style.C++}function DA(a,b,c){a.style.h||(a.style.h=[]);a=a.style.h;var d=new Zu;nv(d);d.b=c.b;d.a=c.a;d.f=Ad(c.f);d.c=c.c;d.g=c.g;d.h=c.h;a[b]=d}function EA(a,b,c){a.style.b[b+0]=c>>16&255;a.style.b[b+1]=c>>8&255;a.style.b[b+2]=c&255;a.style.b[b+3]=c>>24&255}function FA(a,b,c){a=a.style.b;a[b]=Math.floor(c/4%128);a[b+1]=Math.floor(64*c)%256} +function GA(a,b,c,d,e){var f=null;if(!b){if(!e)return null;f=b=[]}if(!b[c]){if(!e)return null;b[c]=[]}(b[c][d]=e)&&a.style.o++;return f}function HA(a,b,c,d){if(b=GA(a,a.style.v,b,c,d))a.style.v=b}function IA(a,b,c,d){if(b=GA(a,a.style.A,b,c,d))a.style.A=b}function JA(a,b,c,d){if(b=GA(a,a.style.u,b,c,d))a.style.u=b} +function KA(a,b,c){if(b>c)KA(a,c,b);else if(!(1>=c-b)){var d=qA(a.style,b);if(d){var e=qA(a.style,c);if(e){for(var f=b+1;f<c;f++){var g=qA(a.style,f);if(!g)return;rA(d,e,g,(f-b)/(c-b),sA(b,c,f))}for(f=b+1;f<c;f++)for(CA(a,f,fA(a.style,b)),d=0;d<a.style.c;d++)HA(a,d,f,vA(a.style.v,d,b)),IA(a,d,f,vA(a.style.A,d,b)),JA(a,d,f,vA(a.style.u,d,b));for(f=b+1;f<c;f++)d=a.style,e=b,g=f,d.f?d.f[g]=d.f[e]:d.a?d.a[g]=d.a[e]:d.g?d.g[g]=d.g[e]:d.h?d.h[g]=d.h[e]:d.i&&(d.i[g]=d.i[e])}}}} +function sA(a,b,c){a=Math.pow(2,a);return(Math.pow(2,c)-a)/(Math.pow(2,b)-a)} +function rA(a,b,c,d,e){function f(e){var f=a[e+3],g=b[e+3];0<f&&0<g?(c[e]=$n(a[e],b[e],d),c[e+1]=$n(a[e+1],b[e+1],d),c[e+2]=$n(a[e+2],b[e+2],d)):0<f?(c[e]=a[e],c[e+1]=a[e+1],c[e+2]=a[e+2]):0<g&&(c[e]=b[e],c[e+1]=b[e+1],c[e+2]=b[e+2]);c[e+3]=$n(a[e+3],b[e+3],d)}function g(d){var f=$n(Tz(a,d),Tz(b,d),e);c[d]=Math.floor(f/4%128);c[d+1]=Math.floor(64*f)%256}function h(d){var f=8*$n(Wz(a,d+l.nd),Wz(b,d+l.nd),e);0>f&&(f=-f+128);c[d+l.nd]=Math.floor(f)}function k(a){c[a+l.Tc]=b[a+l.Tc];c[a+l.Tc+1]=b[a+l.Tc+ +1]}var l=Sz;f(0);f(4);f(8);f(12+l.Zd);g(12+l.$d);h(12);k(12);f(24+l.Zd);g(24+l.$d);h(24);k(24)}var cA=new Rz;function LA(a){Pp.call(this);this.h=a;this.f={};this.f[0]=cA;this.b=0;this.c=this.a=null;this.g=1}F(LA,Pp);function MA(a,b,c){a.a=b;a.c=c||null}LA.prototype.X=function(){this.c=this.a=null};function NA(a){this.f=a;this.b=[];this.a=[];this.c=!1}function OA(a,b){a=qr(a.f,"A"+a.b[b]);return-1==a?0:a};function PA(a,b,c){Pp.call(this);this.j=a;this.h=b;this.a=null;this.g={};this.c=[];this.f=this.b=null;this.i=c}F(PA,Pp);function QA(a){var b=a.c.length-1;a=a.h.b;return b>a?b:a}function RA(a,b){var c=a.c[b];a=c?c:(a=a.h.f[b])?a:cA;return a}function SA(a,b){for(var c=[],d=[],e=a.c,f=0;f<b.length;++f){var g=b[f],h=g.G(),k=e[h];k&&yA(k,g)||(e[h]=g,c.push(h),d.push(g))}c.length&&a.b&&a.b.call(a.f,c,d)} +function TA(a,b){if(a.a){for(var c=[],d=0;d<b.length;++d){var e=b[d],f=a.g[e];B(f)&&(c.push(f),delete a.g[e])}if(c.length){b=a.j;d=a.a;e=[];for(f=0;f<c.length;++f)UA(b,d,c[f],e);SA(a,e)}}}function VA(a,b,c){a.b=b;a.f=c||null}function WA(a){a.b=null;a.f=null}PA.prototype.X=function(){WA(this)};var XA="StopIteration"in x?x.StopIteration:{message:"StopIteration",stack:""};function YA(){}YA.prototype.next=function(){throw XA;};YA.prototype.od=function(){return this};function ZA(a){if(a instanceof YA)return a;if("function"==typeof a.od)return a.od(!1);if(xa(a)){var b=0,c=new YA;c.next=function(){for(;;){if(b>=a.length)throw XA;if(b in a)return a[b++];b++}};return c}throw Error("Not implemented");} +function $A(a,b){if(xa(a))try{Ma(a,b,void 0)}catch(c){if(c!==XA)throw c;}else{a=ZA(a);try{for(;;)b.call(void 0,a.next(),void 0,a)}catch(c){if(c!==XA)throw c;}}};function aB(a,b){this.b={};this.a=[];this.f=this.c=0;var c=arguments.length;if(1<c){if(c%2)throw Error("Uneven number of arguments");for(var d=0;d<c;d+=2)this.set(arguments[d],arguments[d+1])}else if(a)if(a instanceof aB)for(c=a.nb(),d=0;d<c.length;d++)this.set(c[d],a.get(c[d]));else for(d in a)this.set(d,a[d])}r=aB.prototype;r.ob=function(){bB(this);for(var a=[],b=0;b<this.a.length;b++)a.push(this.b[this.a[b]]);return a};r.nb=function(){bB(this);return this.a.concat()}; +r.clear=function(){this.b={};this.f=this.c=this.a.length=0};function bB(a){if(a.c!=a.a.length){for(var b=0,c=0;b<a.a.length;){var d=a.a[b];cB(a.b,d)&&(a.a[c++]=d);b++}a.a.length=c}if(a.c!=a.a.length){var e={};for(c=b=0;b<a.a.length;)d=a.a[b],cB(e,d)||(a.a[c++]=d,e[d]=1),b++;a.a.length=c}}r.get=function(a,b){return cB(this.b,a)?this.b[a]:b};r.set=function(a,b){cB(this.b,a)||(this.c++,this.a.push(a),this.f++);this.b[a]=b}; +r.forEach=function(a,b){for(var c=this.nb(),d=0;d<c.length;d++){var e=c[d],f=this.get(e);a.call(b,f,e,this)}};r.od=function(a){bB(this);var b=0,c=this.f,d=this,e=new YA;e.next=function(){if(c!=d.f)throw Error("The map has changed since the iterator was created");if(b>=d.a.length)throw XA;var e=d.a[b++];return a?e:d.b[e]};return e};function cB(a,b){return Object.prototype.hasOwnProperty.call(a,b)};function dB(a){if(a.ob&&"function"==typeof a.ob)return a.ob();if(pa(a))return a.split("");if(xa(a)){for(var b=[],c=a.length,d=0;d<c;d++)b.push(a[d]);return b}b=[];c=0;for(d in a)b[c++]=a[d];return b} +function eB(a,b,c){if(a.forEach&&"function"==typeof a.forEach)a.forEach(b,c);else if(xa(a)||pa(a))Ma(a,b,c);else{if(a.nb&&"function"==typeof a.nb)var d=a.nb();else if(a.ob&&"function"==typeof a.ob)d=void 0;else if(xa(a)||pa(a)){d=[];for(var e=a.length,f=0;f<e;f++)d.push(f)}else for(f in d=[],e=0,a)d[e++]=f;e=dB(a);f=e.length;for(var g=0;g<f;g++)b.call(c,e[g],d&&d[g],a)}};var fB=/^(?:([^:/?#.]+):)?(?:\/\/(?:([^/?#]*)@)?([^/#?]*?)(?::([0-9]+))?(?=[/#?]|$))?([^?#]+)?(?:\?([^#]*))?(?:#([\s\S]*))?$/;function gB(a,b){if(a){a=a.split("&");for(var c=0;c<a.length;c++){var d=a[c].indexOf("="),e=null;if(0<=d){var f=a[c].substring(0,d);e=a[c].substring(d+1)}else f=a[c];b(f,e?decodeURIComponent(e.replace(/\+/g," ")):"")}}} +function hB(a,b){if(!b)return a;var c=a.indexOf("#");0>c&&(c=a.length);var d=a.indexOf("?");if(0>d||d>c){d=c;var e=""}else e=a.substring(d+1,c);a=[a.substr(0,d),e,a.substr(c)];c=a[1];a[1]=b?c?c+"&"+b:b:c;return a[0]+(a[1]?"?"+a[1]:"")+a[2]}function iB(a,b,c){if(va(b))for(var d=0;d<b.length;d++)iB(a,String(b[d]),c);else null!=b&&c.push(a+(""===b?"":"="+encodeURIComponent(String(b))))}function jB(a,b){var c=[];for(b=b||0;b<a.length;b+=2)iB(a[b],a[b+1],c);return c.join("&")} +function kB(a){var b=[],c;for(c in a)iB(c,a[c],b);return b.join("&")}function lB(a,b){var c=2==arguments.length?jB(arguments[1],0):jB(arguments,1);return hB(a,c)};function mB(a){this.c=this.j=this.b="";this.i=null;this.g=this.h="";this.a=!1;if(a instanceof mB){this.a=B(void 0)?void 0:a.a;nB(this,a.b);this.j=a.j;this.c=a.c;oB(this,a.i);this.h=a.h;var b=a.f;var c=new pB;c.c=b.c;b.a&&(c.a=new aB(b.a),c.b=b.b);qB(this,c);this.g=a.g}else a&&(b=String(a).match(fB))?(this.a=!1,nB(this,b[1]||"",!0),this.j=rB(b[2]||""),this.c=rB(b[3]||"",!0),oB(this,b[4]),this.h=rB(b[5]||"",!0),qB(this,b[6]||"",!0),this.g=rB(b[7]||"")):(this.a=!1,this.f=new pB(null,this.a))} +mB.prototype.toString=function(){var a=[],b=this.b;b&&a.push(sB(b,tB,!0),":");var c=this.c;if(c||"file"==b)a.push("//"),(b=this.j)&&a.push(sB(b,tB,!0),"@"),a.push(encodeURIComponent(String(c)).replace(/%25([0-9a-fA-F]{2})/g,"%$1")),c=this.i,null!=c&&a.push(":",String(c));if(c=this.h)this.c&&"/"!=c.charAt(0)&&a.push("/"),a.push(sB(c,"/"==c.charAt(0)?uB:vB,!0));(c=this.f.toString())&&a.push("?",c);(c=this.g)&&a.push("#",sB(c,wB));return a.join("")}; +function nB(a,b,c){a.b=c?rB(b,!0):b;a.b&&(a.b=a.b.replace(/:$/,""))}function oB(a,b){if(b){b=Number(b);if(isNaN(b)||0>b)throw Error("Bad port number "+b);a.i=b}else a.i=null}function qB(a,b,c){b instanceof pB?(a.f=b,xB(a.f,a.a)):(c||(b=sB(b,yB)),a.f=new pB(b,a.a))}function rB(a,b){return a?b?decodeURI(a.replace(/%25/g,"%2525")):decodeURIComponent(a):""}function sB(a,b,c){return pa(a)?(a=encodeURI(a).replace(b,zB),c&&(a=a.replace(/%25([0-9a-fA-F]{2})/g,"%$1")),a):null} +function zB(a){a=a.charCodeAt(0);return"%"+(a>>4&15).toString(16)+(a&15).toString(16)}var tB=/[#\/\?@]/g,vB=/[#\?:]/g,uB=/[#\?]/g,yB=/[#\?@]/g,wB=/#/g;function pB(a,b){this.b=this.a=null;this.c=a||null;this.f=!!b}function AB(a){a.a||(a.a=new aB,a.b=0,a.c&&gB(a.c,function(b,c){a.add(decodeURIComponent(b.replace(/\+/g," ")),c)}))}r=pB.prototype;r.add=function(a,b){AB(this);this.c=null;a=BB(this,a);var c=this.a.get(a);c||this.a.set(a,c=[]);c.push(b);this.b+=1;return this}; +function CB(a,b){AB(a);b=BB(a,b);cB(a.a.b,b)&&(a.c=null,a.b-=a.a.get(b).length,a=a.a,cB(a.b,b)&&(delete a.b[b],a.c--,a.f++,a.a.length>2*a.c&&bB(a)))}r.clear=function(){this.a=this.c=null;this.b=0};function DB(a,b){AB(a);b=BB(a,b);return cB(a.a.b,b)}r.forEach=function(a,b){AB(this);this.a.forEach(function(c,d){Ma(c,function(c){a.call(b,c,d,this)},this)},this)};r.nb=function(){AB(this);for(var a=this.a.ob(),b=this.a.nb(),c=[],d=0;d<b.length;d++)for(var e=a[d],f=0;f<e.length;f++)c.push(b[d]);return c}; +r.ob=function(a){AB(this);var b=[];if(pa(a))DB(this,a)&&(b=Ua(b,this.a.get(BB(this,a))));else{a=this.a.ob();for(var c=0;c<a.length;c++)b=Ua(b,a[c])}return b};r.set=function(a,b){AB(this);this.c=null;a=BB(this,a);DB(this,a)&&(this.b-=this.a.get(a).length);this.a.set(a,[b]);this.b+=1;return this};r.get=function(a,b){a=a?this.ob(a):[];return 0<a.length?String(a[0]):b}; +r.toString=function(){if(this.c)return this.c;if(!this.a)return"";for(var a=[],b=this.a.nb(),c=0;c<b.length;c++){var d=b[c],e=encodeURIComponent(String(d));d=this.ob(d);for(var f=0;f<d.length;f++){var g=e;""!==d[f]&&(g+="="+encodeURIComponent(String(d[f])));a.push(g)}}return this.c=a.join("&")};function BB(a,b){b=String(b);a.f&&(b=b.toLowerCase());return b} +function xB(a,b){b&&!a.f&&(AB(a),a.c=null,a.a.forEach(function(a,b){var c=b.toLowerCase();b!=c&&(CB(this,b),CB(this,c),0<a.length&&(this.c=null,this.a.set(BB(this,c),Va(a)),this.b+=a.length))},a));a.f=b}r.zf=function(a){for(var b=0;b<arguments.length;b++)eB(arguments[b],function(a,b){this.add(b,a)},this)};function EB(a,b,c,d){c.style.f||(c.style.f=[]);var e=c.style.f,f=new Ou;jv(f);f.a=Bd(a.a,hw);f.f=a.f;f.g=a.g;f.h=a.h;f.c=a.c;f.b=Ad(a.b);f.l=a.l;f.j=a.j;f.i=a.i;e[b]=f;e=[];if(null!=a.a)e=a.a;else if(null!=a.b){f=a.b;for(var g=0;g<f.length;++g)e.push(Pv(d,f[g]))}c.style.c<e.length&&BA(c,e.length);for(g=0;g<e.length;g++)FB(e[g],g,b,c);a=null==a.f?0:a.f;c.style.D=!0;EA(c,36*b+12,a)} +function GB(a,b,c,d,e){d.style.a||(d.style.a=[]);var f=d.style.a,g=new Pu;Xv(g,a);f[b]=g;if(null!=a.a&&(null==a.h||!a.h))if(f=ew(a),null!=f.a||null!=f.b||null!=f.g){if(!fA(d.style,b)){g=[];if(null!=f.b||null!=f.g){gw(f);var h=f.b;for(var k=0;k<h.length;++k)g.push(Sv(e,h[k]))}if(null!=f.a)for(f=f.a,k=0;k<f.length;++k)g.push(f[k]);HB(g,a,b,c,d,e)}}else d.style.j||(g=null==f.l?0:f.l,d.style.j=!0,EA(d,0,g),g=null==f.m?0:f.m,d.style.j=!0,EA(d,4,g),f=(null==f.o?0:f.o)/8,d.style.j=!0,FA(d,8,f));f=null== +a.f?0:a.f;d.style.l=!0;EA(d,36*b+16,f);null!=a.c&&(f=dw(a),0<(null==f.f?0:f.f)&&(f=null==a.o?0:a.o,d.style.s=!0,EA(d,36*b+20,f)));if(null!=a.b||null!=a.g||null!=a.j){f=[];if(null!=a.g||null!=a.j)for(Wv(a),k=a.g,g=0;g<k.length;++g)f.push(Sv(e,k[g]));if(null!=a.b)for(k=a.b,g=0;g<k.length;++g)f.push(k[g]);HB(f,a,b,c,d,e)}} +function HB(a,b,c,d,e,f){if(a.length){var g=[];for(var h=[],k=[],l=!1,m=!1,n=0;n<a.length;n++){var p=a[n];if(null!=p.a&&(null==p.a?0:p.a)||null!=p.b){var q=IB(p,f);if(0==q.lastIndexOf("icon/name=",0)){var t=q.indexOf("&");-1==t&&(t=q.length);g.push(q.substring(10,t));null!=p.g?(l=!0,h.push((null==p.g?4278190080:p.g).toString(16))):h.push("ff000000");null!=p.f?(m=!0,k.push((null==p.f?0:p.f).toString(16))):k.push("00000000")}}}0==g.length?g="":(n="",l&&(n="&highlight="+h.join(",")),h="",m&&(h="&filter="+ +k.join(",")),g="icon/"+["name=",g.join(","),n,h].join(""));g?(f=[],a="ff000000",null!=b.f&&(a=(null==b.f?0:b.f).toString(16)),f.push("color=",a),null!=b.c&&(b=dw(b),null!=b.c&&f.push("&font=",encodeURIComponent(String(null==b.c?"":b.c))),null!=b.b&&f.push("&psize=",null==b.b?0:b.b),null!=b.a&&(b=null==b.a?0:b.a,k=a="",b&1?a="bold":b&8?a="medium":b&16&&(a="light"),b&2&&(k="italic"),a&&f.push("&font_weight=",a),k&&f.push("&font_style=",k))),d=d.a([g,"&",f.join("")].join("")),CA(e,c,new Ws(d,null))): +1==a.length&&(b=a[0],f=IB(b,f),a=new mB(f),a.b||a.c?CA(e,c,new Ws(f,null==b.h?1:b.h)):(d=d.a(f),CA(e,c,new Ws(d,null))))}}function IB(a,b){var c=null==a.a?"":a.a;if(0==c.lastIndexOf("data:",0))return c;null!=a.b&&(a=null==a.b?-1:a.b,Hv(b),c=b.u[a]+c);b&&(c=(null==b.o?"":b.o)+c+(null==b.s?"":b.s));return c} +function JB(a,b,c,d){c.style.g||(c.style.g=[]);var e=c.style.g,f=new Uu;lv(f);f.a=Bd(a.a,hw);f.j=a.j;f.l=a.l;f.h=a.h;f.g=a.g;f.c=Ad(a.c);f.i=a.i;f.A=a.A;f.f=a.f;f.v=a.v;f.b=a.b;f.s=a.s;f.o=a.o;f.u=a.u;f.m=a.m;f.B=a.B;e[b]=f;f=[];if(null!=a.a)f=a.a;else if(null!=a.c||null!=a.i){kw(a);var g=a.c;for(e=0;e<g.length;++e)f.push(Pv(d,g[e]))}d=f.length;g=0;2<d&&(g=d-2,d=2);c.style.c<d&&BA(c,d);for(e=0;e<d;e++)FB(f[e+g],e,b,c);if(null!=a.f)for(f=null==a.f?"":a.f,e=0;e<d;e++)IA(c,e,b,new Ws(f,1));if(null!= +a.b)for(a=null==a.b?"":a.b,e=0;e<d;e++)JA(c,e,b,new Ws(a,1))}function KB(a,b,c){c.style.i||(c.style.i=[]);var d=c.style.i,e=new Yu;mv(e);e.a=a.a;e.g=a.g;e.b=a.b;e.f=a.f;e.c=a.c;d[b]=e;d=null==a.b?0:a.b;c.style.D=!0;EA(c,36*b+12,d);null!=a.a&&(BA(c,1),EA(c,36*b+24,null==a.a?0:a.a))} +function FB(a,b,c,d){EA(d,36*c+24+12*b+0,null==a.g?0:a.g);FA(d,36*c+24+12*b+4,(null==a.i?0:a.i)/8);var e=(null==a.h?0:a.h)/8*8;0>e&&(e=-e+128);d.style.b[36*c+24+12*b+10]=Math.floor(e);e=[];for(var f=0;f<(a.c?a.c.length:0)&&(e.push(a.c[f]/8),2!=e.length);f++);e.length&&(f=36*c+24+12*b+8,e&&2==e.length?(d.style.b[f+0]=Math.floor(2*e[0]),d.style.b[f+1]=Math.floor(2*e[1])):(d.style.b[f+0]=0,d.style.b[f+1]=0));null!=a.f&&HA(d,b,c,new Ws(null==a.f?"":a.f,1));null!=a.b&&(null===a.b&&(a.b=new Vu),e=a.b,null!= +e.a&&(e=null==e.a?"":e.a,IA(d,b,c,new Ws(e,1))));null!=a.a&&(null===a.a&&(a.a=new Vu),a=a.a,null!=a.a&&(e=null==a.a?"":a.a,JA(d,b,c,new Ws(e,1))))} +function LB(a,b){var c;for(c=0;c<a.length-1;++c)KA(b,a[c],a[c+1]);a=a[a.length-1];var d=a+1;c=22;var e=b.style;0>d&&(d=0);22<c&&(c=22);if(!(d>c||d==c&&a==d)){var f=qA(b.style,a);if(f)for(;d<=c;d++)if(d!=a){e.f?e.f[d]=e.f[a]:e.a?e.a[d]=e.a[a]:e.g?e.g[d]=e.g[a]:e.h?e.h[d]=e.h[a]:e.i&&(e.i[d]=e.i[a]);b.style.b.set(f,12+36*d);CA(b,d,fA(b.style,a));for(var g=0;g<b.style.c;g++)HA(b,g,d,vA(b.style.v,g,a)),IA(b,g,d,vA(b.style.A,g,a)),JA(b,g,d,vA(b.style.u,g,a))}}};function MB(a,b){this.a=a;this.b=b||null} +function UA(a,b,c,d){var e=b.b[c];uv(e);var f=e.a?e.a.length:0;if(0!=f){var g=null,h=null,k=null,l=null;c=null;for(var m=[],n=[],p=[],q=[],t=[],v=0;v<f;v++){var u=e;var w=v;uv(u);w=u.a[w];u=w.getZoom();if(null!=w.c){var y=b;var A=null==w.c?0:w.c;Bv(y);y=y.i[A];h||(h=new zA);n.push(u);JB(y,u,h,b)}null!=w.a&&(y=b,A=null==w.a?0:w.a,zv(y),y=y.f[A],g||(g=new zA),m.push(u),EB(y,u,g,b));null!=w.g&&(y=b,A=null==w.g?0:w.g,Dv(y),y=y.v[A],k||(k=new zA),p.push(u),KB(y,u,k));null!=w.b&&(y=b,A=null==w.b?0:w.b, +Av(y),y=y.h[A],l||(l=new zA),q.push(u),GB(y,u,a.b,l,b));null!=w.f&&(y=b,w=null==w.f?0:w.f,Ev(y),w=y.l[w],c||(c=new zA),t.push(u),DA(c,u,w))}b=e.wa();h&&(LB(n,h),h=h.style,n=pr(a.a,"L"+b),h.B=n,d.push(h));g&&(LB(m,g),h=g.style,g=pr(a.a,"A"+b),h.B=g,d.push(h));k&&(LB(p,k),h=k.style,k=pr(a.a,"V"+b),h.B=k,d.push(h));l&&(LB(q,l),h=l.style,l=pr(a.a,"B"+b),h.B=l,d.push(h));c&&(LB(t,c),h=c.style,a=pr(a.a,"R"+b),h.B=a,d.push(h))}};function NB(a,b){this.a=a;this.b=b||null};function OB(a,b){Pp.call(this);this.g=new MB(a,b);this.b=new LA(a,new NB(a,b));this.c=new NA(a);this.a={};a.f=this.f;a.g=this||null}F(OB,Pp);function PB(a,b){b=Ms(b);var c=a.a[b];c||(c=a.a[b]=new PA(a.g,a.b,a.c),Qp(a,c));return c}OB.prototype.f=function(a){for(var b in this.a)this.a[b].c[a]=null};var QB=4/127;function RB(a,b,c){var d=a.i;this.i=a;this.h=b;this.b=new Mq(a,Math.min(Math.ceil(1024*c),d),Math.min(Math.ceil(128*c),d),6408,9729,!0,Math.ceil(128*c));this.a=new Mq(a,1024,64,6408,9728,!1,64,new fo(1,16));this.c=new Mq(a,2048,1024,6406,9729,!1,256,new fo(8,12));this.f=new Mq(a,2048,512,6408,9728,!1,256,new fo(16,3));this.g=new Mq(a,Math.min(Math.ceil(4096*c),d),Math.min(Math.ceil(512*c),d),6406,9729,!1,Math.ceil(128*c),new fo(4,2))}RB.prototype.getContext=function(){return this.i}; +RB.prototype.$=function(){this.b.$();this.a.$();this.c.$();this.f.$();this.g.$()};function SB(a,b,c){this.a=a;this.c=b;this.b=c}function TB(a,b){if(0==b)return 0;if(1==b)return 1;var c=$n(0,a.a,b),d=$n(a.a,a.b,b);a=$n(a.b,1,b);c=$n(c,d,b);d=$n(d,a,b);return $n(c,d,b)}function UB(a,b){if(0==b)return 0;if(1==b)return 1;var c=$n(0,a.c,b);a=$n(a.c,1,b);var d=$n(1,1,b);c=$n(c,a,b);a=$n(a,d,b);return $n(c,a,b)} +function VB(a,b){var c=(b-0)/1;if(0>=c)return 0;if(1<=c)return 1;for(var d=0,e=1,f=0,g=0;8>g;g++){f=TB(a,c);var h=(TB(a,c+1E-6)-f)/1E-6;if(1E-6>Math.abs(f-b))return c;if(1E-6>Math.abs(h))break;else f<b?d=c:e=c,c-=(f-b)/h}for(g=0;1E-6<Math.abs(f-b)&&8>g;g++)f<b?(d=c,c=(c+e)/2):(e=c,c=(c+d)/2),f=TB(a,c);return c};function WB(a,b,c){a=new SB(a,b,c);var d=Array(51);for(b=0;51>b;b++)d[b]=UB(a,VB(a,b/50));return function(a){if(0>=a)return 0;if(1<=a)return 1;var b=50*a;a=Math.floor(b);b-=a;return d[a]*(1-b)+d[a+1]*b}}var XB=WB(0,0,.58);WB(.52,0,.48);WB(.52,0,.25);WB(.36,.67,.533);WB(.24,.67,.533);WB(.56,1,.56);WB(.91,1,.82);function YB(a,b){this.m=b;this.i=this.h=this.f=this.b=this.a=null;this.c=0;this.l=!0;this.j=-1;this.g=!1;MA(a.b,this.o,this)}function ZB(a){return a.l&&E()<a.j}YB.prototype.o=function(a,b){this.c++;this.f&&this.f.call(this.h,[a],[b])};YB.prototype.s=function(a,b){this.f&&this.f.call(this.h,a,b)};function Qr(a){a.i&&a.i.call(null);ZB(a)?(a.g=!0,a.m.Pd(a)):a.g=!1};function $B(a){a&=4294967295;var b="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@#"[a&63];for(a>>=6;a;)b+="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@#"[a&63],a>>=6;return b}function aC(a){return"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@#"[a&63]};function bC(a){var b=a.length;if(!b)return null;for(var c=a[0].b,d=c,e=a[0].a,f=e,g=1;g<b;++g){var h=a[g].b,k=a[g].a;h<c?c=h:h>d&&(d=h);k<e?e=k:k>f&&(f=k)}k=1<<a[0].getZoom();if(0==c&&d==k-1){d=0;c=k-1;for(g=0;g<b;++g)h=a[g].b,h>d&&h<c&&(c-h>h-d?d=h:c=h);c-1==d?(c=0,d=k-1):d+=k}return{oa:c,Yc:d,xc:e,bd:f}}function cC(a,b){var c=30-a.getZoom(),d=a.b<<c;a=a.a<<c;var e=d+(1<<c)-1;c=a+(1<<c)-1;var f=30-b.getZoom(),g=b.b<<f;b=b.a<<f;return g<=e&&d<=g+(1<<f)-1&&b<=c&&a<=b+(1<<f)-1};function dC(a,b,c,d){this.Ha=a;this.a=b||0;this.c=c||Rs;d?a=d:(b=this.c,a=Fs(b.a,a,b.f));this.b=a;c=this.Ha;a=this.b;b=eC(this.a,this.c);b+=":"+c.aa();if(a){c=Array(a.length);for(d=0;d<a.length;++d){var e=a[d];c[d]=null!=e?0<=e?$B(e):"-1":""}b+="@"+c.join(",")}this.h=b;this.g=this.f=null}function eC(a,b){return 0!=a&&4!=a?aC(a):Qs(b)}dC.prototype.aa=function(){return this.h};function fC(a,b){b=b.b;if(a.b.length!=b.length)return!1;for(var c=0,d=b.length;c<d;c++)if(b[c]!=a.b[c])return!1;return!0} +function gC(a){return 0==a.a&&!!a.c.b}function hC(a){if(gC(a)&&null==a.g){var b=a.c.b;var c=a.c;var d=a.b;if(c.b){c=Array(c.b.a.a.length);for(var e=0;e<c.length;++e)c[e]=d[e];d=c}b=new dC(a.Ha,a.a,b,d);a.g=b}}function iC(a){return a.Ha.b}function jC(a){return a.Ha.a}dC.prototype.getZoom=function(){return this.Ha.getZoom()};dC.prototype.Ea=function(){return this.a};dC.prototype.ba=function(){return this.c};function kC(a,b,c){this.b=a;this.a=b;this.f=c;this.c=null}kC.prototype.getZoom=function(){return this.f};kC.prototype.aa=function(){this.c||(this.c=$B(this.b)+","+$B(this.a)+","+aC(this.f));return this.c};function lC(a){for(var b=new Es,c=0;c<Fe(a,1);c++){var d=b,e=mC(a,c);d.a.push(e);d.b.push(void 0)}return b}function nC(a){var b=new Js;a=new oC(a.data[2]);for(var c=0;c<Fe(a,11);c++){var d=new Sn(Ee(a,11,c));b.a.push(d)}return b};function pC(a){this.data=a||[]}var qC;F(pC,W);function rC(a){this.data=a||[]}var sC;F(rC,W);function tC(a){this.data=a||[]}var uC;F(tC,W);function vC(){qC||(qC={a:-1,F:[]},qC.F=[,ae(512),ae(512),Zd(47.651318),Zd(-122.35305),Zd(15),$d,$d,$d,Zd(-212),Zd(40),Zd(13.1),ce,ce,Vd("s","Default"),Vd("s","en"),R,R,R,ge(!0),P,R,ke,R,P,U,ge(!0),R,R,ge(!0),R,R,P,ke,P]);return qC}pC.prototype.getZoom=function(){return X(this,4,15)};pC.prototype.Ea=function(){return Ce(this,11)[void 0]}; +function wC(){var a=uC={a:-1,F:[]},b=V(new pC([]),vC());sC||(sC={a:-1,F:[]},sC.F=[,V(new pC([]),vC()),P]);a.F=[,b,pe(sC),R,ge(!0),ge(!0),Zd(1),$d,$d,R,ae(2),R]};function xC(a){if(!xe(a,0))throw"MultiViewports must have an initial viewport set.";this.a=[new pC(a.data[0])];var b=new pC;He(b,new pC(a.data[0]));for(var c=Fe(a,1),d=0;d<c;d++){var e=new pC((new rC(Ee(a,1,d))).data[0]),f=X(new rC(Ee(a,1,d)),1),g=new pC;xe(e,0)&&(g.data[0]=1*(X(e,0,512)-X(b,0,512))/f);xe(e,1)&&(g.data[1]=1*(X(e,1,512)-X(b,1,512))/f);xe(e,2)&&(g.data[2]=1*(X(e,2,47.651318)-X(b,2,47.651318))/f);xe(e,3)&&(g.data[3]=1*(X(e,3,-122.35305)-X(b,3,-122.35305))/f);if(xe(e,4)){var h=1*(e.getZoom()- +b.getZoom())/f;g.data[4]=h}xe(e,5)&&(g.data[5]=1*(X(e,5)-X(b,5))/f);xe(e,6)&&(g.data[6]=1*(X(e,6)-X(b,6))/f);xe(e,7)&&(g.data[7]=1*(X(e,7)-X(b,7))/f);xe(e,8)&&(g.data[8]=1*(X(e,8,-212)-X(b,8,-212))/f);xe(e,9)&&(g.data[9]=1*(X(e,9,40)-X(b,9,40))/f);xe(e,10)&&(g.data[10]=1*(X(e,10,13.1)-X(b,10,13.1))/f);for(h=0;h<f-1;++h){xe(e,0)&&(b.data[0]=X(b,0,512)+X(g,0,512));xe(e,1)&&(b.data[1]=X(b,1,512)+X(g,1,512));xe(e,2)&&(b.data[2]=X(b,2,47.651318)+X(g,2,47.651318));xe(e,3)&&(b.data[3]=X(b,3,-122.35305)+ +X(g,3,-122.35305));if(xe(e,4)){var k=b.getZoom()+g.getZoom();b.data[4]=k}xe(e,5)&&(b.data[5]=X(b,5)+X(g,5));xe(e,6)&&(b.data[6]=X(b,6)+X(g,6));xe(e,7)&&(b.data[7]=X(b,7)+X(g,7));xe(e,8)&&(b.data[8]=X(b,8,-212)+X(g,8,-212));xe(e,9)&&(b.data[9]=X(b,9,40)+X(g,9,40));xe(e,10)&&(b.data[10]=X(b,10,13.1)+X(g,10,13.1));k=new pC;He(k,b);this.a.push(k)}e=e.data;f=b.data;for(g=0;g<e.length;g++)null!=e[g]&&(f[g]=e[g]);e=new pC(f.slice());He(b,e);this.a.push(e);Be(b,31)}};function yC(){var a=zC;if("undefined"!=typeof window){var b=function(){return this.getAttribute("src")},c=function(b){b=a.call(this,b);this.setAttribute("src",b)},d=this.a=document.createElement;document.createElement=function(a){var e=d.call(this,a);"IMG"==a.toUpperCase()&&Object.defineProperty(e,"src",{enumerable:!0,configurable:!0,get:b,set:c});return e}}}yC.prototype.$=function(){"undefined"!=typeof window&&(document.createElement=this.a)};function AC(){var a=zC,b=this.a=XMLHttpRequest.prototype.open;XMLHttpRequest.prototype.open=function(c,d,e,f,g){for(var h=a.call(this,d),k=Array(arguments.length),l=0;l<k.length;l++)k[l]=1==l?h:arguments[l];b.apply(this,k)}}AC.prototype.$=function(){XMLHttpRequest.prototype.open=this.a};function BC(a,b){this.c=a;this.f=b;this.b=0;this.a=null}BC.prototype.get=function(){if(0<this.b){this.b--;var a=this.a;this.a=a.next;a.next=null}else a=this.c();return a};function CC(a,b){a.f(b);100>a.b&&(a.b++,b.next=a.a,a.a=b)};function DC(){this.b=this.a=null}var FC=new BC(function(){return new EC},function(a){a.reset()});DC.prototype.add=function(a,b){var c=FC.get();c.set(a,b);this.b?this.b.next=c:this.a=c;this.b=c};function GC(){var a=HC,b=null;a.a&&(b=a.a,a.a=a.a.next,a.a||(a.b=null),b.next=null);return b}function EC(){this.next=this.scope=this.a=null}EC.prototype.set=function(a,b){this.a=a;this.scope=b;this.next=null};EC.prototype.reset=function(){this.next=this.scope=this.a=null};function IC(a,b){JC||KC();LC||(JC(),LC=!0);HC.add(a,b)}var JC;function KC(){if(-1!=String(x.Promise).indexOf("[native code]")){var a=x.Promise.resolve(void 0);JC=function(){a.then(MC)}}else JC=function(){ur(MC)}}var LC=!1,HC=new DC;function MC(){for(var a;a=GC();){try{a.a.call(a.scope)}catch(b){tr(b)}CC(FC,a)}LC=!1};function NC(a){switch(a){case 200:case 201:case 202:case 204:case 206:case 304:case 1223:return!0;default:return!1}};function OC(){}OC.prototype.a=null;function PC(a){var b;(b=a.a)||(b={},QC(a)&&(b[0]=!0,b[1]=!0),b=a.a=b);return b};var RC;function SC(){}F(SC,OC);function TC(a){return(a=QC(a))?new ActiveXObject(a):new XMLHttpRequest}function QC(a){if(!a.b&&"undefined"==typeof XMLHttpRequest&&"undefined"!=typeof ActiveXObject){for(var b=["MSXML2.XMLHTTP.6.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"],c=0;c<b.length;c++){var d=b[c];try{return new ActiveXObject(d),a.b=d}catch(e){}}throw Error("Could not create ActiveXObject. ActiveX might be disabled, or MSXML might not be installed");}return a.b}RC=new SC;function UC(a){a.prototype.then=a.prototype.then;a.prototype.$goog_Thenable=!0}function VC(a){if(!a)return!1;try{return!!a.$goog_Thenable}catch(b){return!1}};function WC(a,b){this.a=0;this.i=void 0;this.f=this.b=this.c=null;this.g=this.h=!1;if(a!=sa)try{var c=this;a.call(b,function(a){XC(c,2,a)},function(a){XC(c,3,a)})}catch(d){XC(this,3,d)}}function YC(){this.next=this.context=this.b=this.c=this.a=null;this.f=!1}YC.prototype.reset=function(){this.context=this.b=this.c=this.a=null;this.f=!1};var ZC=new BC(function(){return new YC},function(a){a.reset()});function $C(a,b,c){var d=ZC.get();d.c=a;d.b=b;d.context=c;return d} +WC.prototype.then=function(a,b,c){return aD(this,ya(a)?a:null,ya(b)?b:null,c)};UC(WC);WC.prototype.cancel=function(a){0==this.a&&IC(function(){var b=new bD(a);cD(this,b)},this)};function cD(a,b){if(0==a.a)if(a.c){var c=a.c;if(c.b){for(var d=0,e=null,f=null,g=c.b;g&&(g.f||(d++,g.a==a&&(e=g),!(e&&1<d)));g=g.next)e||(f=g);e&&(0==c.a&&1==d?cD(c,b):(f?(d=f,d.next==c.f&&(c.f=d),d.next=d.next.next):dD(c),eD(c,e,3,b)))}a.c=null}else XC(a,3,b)} +function fD(a,b){a.b||2!=a.a&&3!=a.a||gD(a);a.f?a.f.next=b:a.b=b;a.f=b}function aD(a,b,c,d){var e=$C(null,null,null);e.a=new WC(function(a,g){e.c=b?function(c){try{var e=b.call(d,c);a(e)}catch(l){g(l)}}:a;e.b=c?function(b){try{var e=c.call(d,b);!B(e)&&b instanceof bD?g(b):a(e)}catch(l){g(l)}}:g});e.a.c=a;fD(a,e);return e.a}WC.prototype.l=function(a){this.a=0;XC(this,2,a)};WC.prototype.m=function(a){this.a=0;XC(this,3,a)}; +function XC(a,b,c){if(0==a.a){a===c&&(b=3,c=new TypeError("Promise cannot resolve to itself"));a.a=1;a:{var d=c,e=a.l,f=a.m;if(d instanceof WC){fD(d,$C(e||sa,f||null,a));var g=!0}else if(VC(d))d.then(e,f,a),g=!0;else{if(za(d))try{var h=d.then;if(ya(h)){hD(d,h,e,f,a);g=!0;break a}}catch(k){f.call(a,k);g=!0;break a}g=!1}}g||(a.i=c,a.a=b,a.c=null,gD(a),3!=b||c instanceof bD||iD(a,c))}} +function hD(a,b,c,d,e){function f(a){h||(h=!0,d.call(e,a))}function g(a){h||(h=!0,c.call(e,a))}var h=!1;try{b.call(a,g,f)}catch(k){f(k)}}function gD(a){a.h||(a.h=!0,IC(a.j,a))}function dD(a){var b=null;a.b&&(b=a.b,a.b=b.next,b.next=null);a.b||(a.f=null);return b}WC.prototype.j=function(){for(var a;a=dD(this);)eD(this,a,this.a,this.i);this.h=!1}; +function eD(a,b,c,d){if(3==c&&b.b&&!b.f)for(;a&&a.g;a=a.c)a.g=!1;if(b.a)b.a.c=null,jD(b,c,d);else try{b.f?b.c.call(b.context):jD(b,c,d)}catch(e){kD.call(null,e)}CC(ZC,b)}function jD(a,b,c){2==b?a.c.call(a.context,c):a.b&&a.b.call(a.context,c)}function iD(a,b){a.g=!0;IC(function(){a.g&&kD.call(null,b)})}var kD=tr;function bD(a){Ja.call(this,a)}F(bD,Ja);bD.prototype.name="cancel";function lD(a,b,c){if(ya(a))c&&(a=D(a,c));else if(a&&"function"==typeof a.handleEvent)a=D(a.handleEvent,a);else throw Error("Invalid listener argument");return 2147483647<Number(b)?-1:x.setTimeout(a,b||0)};function mD(a){rc.call(this);this.headers=new aB;this.s=a||null;this.b=!1;this.m=this.a=null;this.i=this.D=this.B="";this.c=this.A=this.h=this.v=!1;this.g=0;this.j=null;this.f="";this.C=this.l=!1}F(mD,rc);var nD=/^https?$/i,oD=["POST","PUT"],pD=[];function qD(a,b,c,d,e){var f=new mD;pD.push(f);b&&f.cb("complete",b);f.cc("ready",f.pf);rD(f,a,c,d,e)}r=mD.prototype;r.pf=function(){this.$();Ta(pD,this)}; +function rD(a,b,c,d,e){if(a.a)throw Error("[goog.net.XhrIo] Object is active with another request="+a.B+"; newUri="+b);c=c?c.toUpperCase():"GET";a.B=b;a.i="";a.D=c;a.v=!1;a.b=!0;a.a=a.s?TC(a.s):TC(RC);a.m=a.s?PC(a.s):PC(RC);a.a.onreadystatechange=D(a.He,a);try{a.A=!0,a.a.open(c,String(b),!0),a.A=!1}catch(g){sD(a,g);return}b=d||"";var f=new aB(a.headers);e&&eB(e,function(a,b){f.set(b,a)});e=Ra(f.nb());d=x.FormData&&b instanceof x.FormData;!(0<=Ka(oD,c))||e||d||f.set("Content-Type","application/x-www-form-urlencoded;charset=utf-8"); +f.forEach(function(a,b){this.a.setRequestHeader(b,a)},a);a.f&&(a.a.responseType=a.f);"withCredentials"in a.a&&a.a.withCredentials!==a.l&&(a.a.withCredentials=a.l);try{tD(a),0<a.g&&(a.C=uD(a.a),a.C?(a.a.timeout=a.g,a.a.ontimeout=D(a.ef,a)):a.j=lD(a.ef,a.g,a)),a.h=!0,a.a.send(b),a.h=!1}catch(g){sD(a,g)}}function uD(a){return pb&&Ab(9)&&qa(a.timeout)&&B(a.ontimeout)}function Sa(a){return"content-type"==a.toLowerCase()} +r.ef=function(){"undefined"!=typeof oa&&this.a&&(this.i="Timed out after "+this.g+"ms, aborting",this.dispatchEvent("timeout"),this.abort(8))};function sD(a,b){a.b=!1;a.a&&(a.c=!0,a.a.abort(),a.c=!1);a.i=b;vD(a);wD(a)}function vD(a){a.v||(a.v=!0,a.dispatchEvent("complete"),a.dispatchEvent("error"))}r.abort=function(){this.a&&this.b&&(this.b=!1,this.c=!0,this.a.abort(),this.c=!1,this.dispatchEvent("complete"),this.dispatchEvent("abort"),wD(this))}; +r.X=function(){this.a&&(this.b&&(this.b=!1,this.c=!0,this.a.abort(),this.c=!1),wD(this,!0));mD.R.X.call(this)};r.He=function(){this.O()||(this.A||this.h||this.c?xD(this):this.Dd())};r.Dd=function(){xD(this)}; +function xD(a){if(a.b&&"undefined"!=typeof oa&&(!a.m[1]||4!=yD(a)||2!=zD(a)))if(a.h&&4==yD(a))lD(a.He,0,a);else if(a.dispatchEvent("readystatechange"),4==yD(a)){a.b=!1;try{if(AD(a))a.dispatchEvent("complete"),a.dispatchEvent("success");else{try{var b=2<yD(a)?a.a.statusText:""}catch(c){b=""}a.i=b+" ["+zD(a)+"]";vD(a)}}finally{wD(a)}}}function wD(a,b){if(a.a){tD(a);var c=a.a,d=a.m[0]?sa:null;a.a=null;a.m=null;b||a.dispatchEvent("ready");try{c.onreadystatechange=d}catch(e){}}} +function tD(a){a.a&&a.C&&(a.a.ontimeout=null);a.j&&(x.clearTimeout(a.j),a.j=null)}function AD(a){var b=zD(a),c;if(!(c=NC(b))){if(b=0===b)a=String(a.B).match(fB)[1]||null,!a&&x.self&&x.self.location&&(a=x.self.location.protocol,a=a.substr(0,a.length-1)),b=!nD.test(a?a.toLowerCase():"");c=b}return c}function yD(a){return a.a?a.a.readyState:0}function zD(a){try{return 2<yD(a)?a.a.status:-1}catch(b){return-1}}function BD(a){try{return a.a?a.a.responseText:""}catch(b){return""}} +r.$c=function(){try{if(!this.a)return null;if("response"in this.a)return this.a.response;switch(this.f){case "":case "text":return this.a.responseText;case "arraybuffer":if("mozResponseArrayBuffer"in this.a)return this.a.mozResponseArrayBuffer}return null}catch(a){return null}};Hb(function(a){mD.prototype.Dd=a(mD.prototype.Dd)});function CD(){this.i=this.g=this.a=this.h=this.f=this.c=this.b=null}function DD(){this.a=null}CD.prototype.w=function(){var a=[];if(null!==this.b){var b=this.b;a[0]=b}ED(this);null!==this.c&&(b=this.c,b=Dc(b),a[1]=b);null!==this.a&&(b=this.a,a[2]=b);null!==this.g&&(b=this.g,a[3]=b);return a};CD.prototype.getExtension=function(){return null}; +function FD(a,b){for(a.i=jd(b);G(b);)switch(b.a){case 1:var c=L(b);a.b=c;break;case 2:null===a.f&&(a.f=b.b);kd(b);a.h=id(b);break;case 3:c=L(b);a.a=c;break;case 4:c=J(b);a.g=c;break;default:H(b)}}CD.prototype.$c=function(){ED(this);return this.c};function ED(a){null!=a.f&&null==a.c&&(a.c=Gd(a.i,a.f,a.h))}DD.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;b=b.slice();for(var c=0;c<b.length;c++)b[c]=b[c].w();a[0]=b}return a};DD.prototype.getExtension=function(){return null};var GD={},HD=null,ID=null;function zC(a){return GD[a]||a} +function JD(a){HD&&HD.$();HD=new yC;ID&&ID.$();ID=new AC;for(var b in GD)URL.revokeObjectURL(GD[b]);GD={};b=new mD;b.f="arraybuffer";b.cb("complete",function(){if(AD(this)){var b=this.$c(),d=new DD;for(b=gd(b);G(b);)switch(b.a){case 1:var e=new CD;O(b,e,FD);d.a=d.a||[];d.a.push(e);break;default:H(b)}hd(b);for(b=0;b<(d.a?d.a.length:0);b++)e=d.a[b],GD[null==e.b?"":e.b]=URL.createObjectURL(new Blob([e.$c()],{type:null==e.a?"":e.a}));a()}else throw Error("Failed to load dataset.");});rD(b,"load_dataset")} +;var KD={warp:"!1m5!1i1500!2i900!3f40.194678!4f-88.926313!5f16!2m5!1m3!3f47.606198!4f-122.332066!32i5000!2i1!2m5!1m3!3f40.416682!4f-3.700418!32i5000!2i1!2m5!1m3!3f37.767454!4f-122.417656!32i5000!2i1!2m5!1m3!3f53.344089!4f-6.267507!32i5000!2i1!2m5!1m3!3f40.714314!4f-74.005977!32i5000!2i1!2m5!1m3!3f47.373092!4f8.521743!32i5000!2i1!2m5!1m3!3f38.895141!4f-77.036433!32i5000!2i1!2m5!1m3!3f35.689527!4f139.691763!32i5000!2i1!2m5!1m3!3f25.775547!4f-80.194761!32i5000!2i1!2m5!1m3!3f52.52335!4f13.411431!32i5000!2i1!2m5!1m3!3f41.8702!4f-87.673774!32i5000!2i1!9b1", +tilt:"!1m5!1i1024!2i768!3f47.651316!4f-122.353048!5f15!2m3!1m1!8f75!2i50!2m3!1m1!7f360!2i200!2m3!1m1!5f16!2i20!2m3!1m1!7f360!2i200!2m3!1m1!8f15!2i50!2m3!1m1!7f180!2i100!2m3!1m1!8f60!2i50!2m3!1m1!5f20!2i20!2m3!1m1!7f45!2i50!2m3!1m1!5f13!2i30!2m4!1m2!3f47.5!4f-122.1!2i50!2m3!1m1!8f0!2i50!4b0!9b1",stress:"!1m5!1i1500!2i900!3f40.194678!4f-88.926313!5f4!2m5!1m3!3f47.606198!4f-122.332066!32i5000!2i50!2m4!1m2!5f16.25!32i15000!2i250!2m5!1m3!3f47.636198!4f-122.302066!32i5000!2i100!2m5!1m3!3f47.576198!4f-122.302066!32i5000!2i100!2m5!1m3!3f47.636198!4f-122.362066!32i5000!2i100!2m5!1m3!3f47.636198!4f-122.362066!32i5000!2i100!2m4!1m2!5f4!32i5000!2i250!2m5!1m3!3f40.416682!4f-3.700418!32i5000!2i50!2m4!1m2!5f16.25!32i15000!2i250!2m5!1m3!3f40.446682!4f-3.670418!32i5000!2i100!2m5!1m3!3f40.386682!4f-3.670418!32i5000!2i100!2m5!1m3!3f40.386682!4f-3.730418!32i5000!2i100!2m5!1m3!3f40.446682!4f-3.730418!32i5000!2i100!2m4!1m2!5f4!32i5000!2i250!2m5!1m3!3f37.767454!4f-122.417656!32i5000!2i50!2m4!1m2!5f16.25!32i15000!2i250!2m5!1m3!3f37.797454!4f-122.387656!32i5000!2i100!2m5!1m3!3f37.737454!4f-122.387656!32i5000!2i100!2m5!1m3!3f37.737454!4f-122.447656!32i5000!2i100!2m5!1m3!3f37.797454!4f-122.447656!32i5000!2i100!2m4!1m2!5f4!32i5000!2i250!2m5!1m3!3f53.344089!4f-6.267507!32i5000!2i50!2m4!1m2!5f16.25!32i15000!2i250!2m5!1m3!3f53.374089!4f-6.237507!32i5000!2i100!2m5!1m3!3f53.314089!4f-6.237507!32i5000!2i100!2m5!1m3!3f53.314089!4f-6.297507!32i5000!2i100!2m5!1m3!3f53.374089!4f-6.297507!32i5000!2i100!2m4!1m2!5f4!32i5000!2i250!2m5!1m3!3f40.714314!4f-74.005977!32i5000!2i50!2m4!1m2!5f16.25!32i15000!2i250!2m5!1m3!3f40.744314!4f-73.975977!32i5000!2i100!2m5!1m3!3f40.684314!4f-73.975977!32i5000!2i100!2m5!1m3!3f40.684314!4f-74.035977!32i5000!2i100!2m5!1m3!3f40.744314!4f-74.035977!32i5000!2i100!2m4!1m2!5f4!32i5000!2i250!2m5!1m3!3f47.373092!4f8.521743!32i5000!2i50!2m4!1m2!5f16.25!32i15000!2i250!2m5!1m3!3f47.403092!4f8.551743!32i5000!2i100!2m5!1m3!3f47.343092!4f8.551743!32i5000!2i100!2m5!1m3!3f47.343092!4f8.491743!32i5000!2i100!2m5!1m3!3f47.403092!4f8.491743!32i5000!2i100!2m4!1m2!5f4!32i5000!2i250!2m5!1m3!3f38.895141!4f-77.036433!32i5000!2i50!2m4!1m2!5f16.25!32i15000!2i250!2m5!1m3!3f38.925141!4f-77.006433!32i5000!2i100!2m5!1m3!3f38.865141!4f-77.006433!32i5000!2i100!2m5!1m3!3f38.865141!4f-77.066433!32i5000!2i100!2m5!1m3!3f38.925141!4f-77.066433!32i5000!2i100!2m4!1m2!5f4!32i5000!2i250!2m5!1m3!3f35.689527!4f139.691763!32i5000!2i50!2m4!1m2!5f16.25!32i15000!2i250!2m5!1m3!3f35.719527!4f139.721763!32i5000!2i100!2m5!1m3!3f35.659527!4f139.721763!32i5000!2i100!2m5!1m3!3f35.659527!4f139.661763!32i5000!2i100!2m5!1m3!3f35.719527!4f139.661763!32i5000!2i100!2m4!1m2!5f4!32i5000!2i250!2m5!1m3!3f25.775547!4f-80.194761!32i5000!2i50!2m4!1m2!5f16.25!32i15000!2i250!2m5!1m3!3f25.805547!4f-80.164761!32i5000!2i100!2m5!1m3!3f25.745547!4f-80.164761!32i5000!2i100!2m5!1m3!3f25.745547!4f-80.224761!32i5000!2i100!2m5!1m3!3f25.805547!4f-80.224761!32i5000!2i100!2m4!1m2!5f4!32i5000!2i250!2m5!1m3!3f52.52335!4f13.411431!32i5000!2i50!2m4!1m2!5f16.25!32i15000!2i250!2m5!1m3!3f52.55335!4f13.441431!32i5000!2i100!2m5!1m3!3f52.49335!4f13.441431!32i5000!2i100!2m5!1m3!3f52.49335!4f13.381431!32i5000!2i100!2m5!1m3!3f52.55335!4f13.381431!32i5000!2i100!2m4!1m2!5f4!32i5000!2i250!2m5!1m3!3f41.8702!4f-87.673774!32i5000!2i50!2m4!1m2!5f16.25!32i15000!2i250!2m5!1m3!3f41.9002!4f-87.643774!32i5000!2i100!2m5!1m3!3f41.8402!4f-87.643774!32i5000!2i100!2m5!1m3!3f41.8402!4f-87.703774!32i5000!2i100!2m5!1m3!3f41.9002!4f-87.703774!32i5000!2i100!2m4!1m2!5f4!32i5000!2i250!9b1", +midzooms:"!1m5!1i2048!2i1024!3f48.85!4f2.34!5f6!2m5!1m3!3f30.05993!4f31.26202!5f9!2i1!2m4!1m2!3f30.03493!4f31.23702!2i20!2m4!1m2!3f30.05993!4f31.26202!2i20!2m3!1m1!5f10!2i20!2m4!1m2!3f30.03493!4f31.23702!2i20!2m4!1m2!3f30.05993!4f31.26202!2i20!2m3!1m1!5f11!2i20!2m4!1m2!3f30.03493!4f31.23702!2i20!2m4!1m2!3f30.05993!4f31.26202!2i20!2m3!1m1!5f12!2i20!2m4!1m2!3f30.03493!4f31.23702!2i20!2m4!1m2!3f30.05993!4f31.26202!2i20!2m3!1m1!5f13!2i20!2m5!1m3!3f41.00561!4f29.01218!5f9!2i1!2m4!1m2!3f40.98061!4f28.98718!2i20!2m4!1m2!3f41.00561!4f29.01218!2i20!2m3!1m1!5f10!2i20!2m4!1m2!3f40.98061!4f28.98718!2i20!2m4!1m2!3f41.00561!4f29.01218!2i20!2m3!1m1!5f11!2i20!2m4!1m2!3f40.98061!4f28.98718!2i20!2m4!1m2!3f41.00561!4f29.01218!2i20!2m3!1m1!5f12!2i20!2m4!1m2!3f40.98061!4f28.98718!2i20!2m4!1m2!3f41.00561!4f29.01218!2i20!2m3!1m1!5f13!2i20!2m5!1m3!3f40.70596!4f-73.978!5f9!2i1!2m4!1m2!3f40.68096!4f-74.003!2i20!2m4!1m2!3f40.70596!4f-73.978!2i20!2m3!1m1!5f10!2i20!2m4!1m2!3f40.68096!4f-74.003!2i20!2m4!1m2!3f40.70596!4f-73.978!2i20!2m3!1m1!5f11!2i20!2m4!1m2!3f40.68096!4f-74.003!2i20!2m4!1m2!3f40.70596!4f-73.978!2i20!2m3!1m1!5f12!2i20!2m4!1m2!3f40.68096!4f-74.003!2i20!2m4!1m2!3f40.70596!4f-73.978!2i20!2m3!1m1!5f13!2i20!2m5!1m3!3f48.85888!4f2.34706!5f9!2i1!2m4!1m2!3f48.83388!4f2.32206!2i20!2m4!1m2!3f48.85888!4f2.34706!2i20!2m3!1m1!5f10!2i20!2m4!1m2!3f48.83388!4f2.32206!2i20!2m4!1m2!3f48.85888!4f2.34706!2i20!2m3!1m1!5f11!2i20!2m4!1m2!3f48.83388!4f2.32206!2i20!2m4!1m2!3f48.85888!4f2.34706!2i20!2m3!1m1!5f12!2i20!2m4!1m2!3f48.83388!4f2.32206!2i20!2m4!1m2!3f48.85888!4f2.34706!2i20!2m3!1m1!5f13!2i20!2m5!1m3!3f35.67347!4f139.7104!5f9!2i1!2m4!1m2!3f35.64847!4f139.6854!2i20!2m4!1m2!3f35.67347!4f139.7104!2i20!2m3!1m1!5f10!2i20!2m4!1m2!3f35.64847!4f139.6854!2i20!2m4!1m2!3f35.67347!4f139.7104!2i20!2m3!1m1!5f11!2i20!2m4!1m2!3f35.64847!4f139.6854!2i20!2m4!1m2!3f35.67347!4f139.7104!2i20!2m3!1m1!5f12!2i20!2m4!1m2!3f35.64847!4f139.6854!2i20!2m4!1m2!3f35.67347!4f139.7104!2i20!2m3!1m1!5f13!2i20!4b0!9b1", +meshes:"!1m5!1i1024!2i768!3f40.6893!4f-74.0442!5f19!2m3!1m1!5f16!2i80!2m4!1m2!3f40.7125!4f-74.0045!2i100!2m3!1m1!5f18!2i40!2m4!1m2!3f40.702!4f-74.0122!2i300!2m4!1m2!3f40.7135!4f-74.0154!2i400!4b0!9b1",buildings:"!1m5!1i1024!2i768!3f47.620458!4f-122.349422!5f16!2m4!1m2!3f47.602!4f-122.325!2i100!2m4!1m2!3f47.591!4f-122.333!2i30!2m3!1m1!5f18!2i10!2m4!1m2!3f47.626!4f-122.331!2i200!2m3!1m1!5f17!2i20!2m4!1m2!3f47.609!4f-122.336!2i65!4b0!9b1",basic_rasterize:"!1m5!1i2048!2i1024!3f47.651316!4f-122.353048!5f15!2m4!1m2!3f47.75!4f-122.35!2i50!2m4!1m2!3f47.75!4f-122.25!2i50!2m4!1m2!3f47.65!4f-122.25!2i50!2m4!1m2!3f47.65!4f-122.35!2i50!2m4!1m2!3f47.7!4f-122.3!2i50!2m3!1m1!5f16!2i20!2m3!1m1!5f14!2i30!2m3!1m1!5f15!2i5!2m3!1m1!7f360!2i100!2m3!1m1!7f45!2i50!2m3!1m1!5f13!2i30!2m4!1m2!3f47.5!4f-122.1!2i50!5b0!9b1!11b1", +basic_large:"!1m5!1i2048!2i1024!3f47.651316!4f-122.353048!5f15!2m4!1m2!3f47.75!4f-122.35!2i50!2m4!1m2!3f47.75!4f-122.25!2i50!2m4!1m2!3f47.65!4f-122.25!2i50!2m4!1m2!3f47.65!4f-122.35!2i50!2m4!1m2!3f47.7!4f-122.3!2i50!2m3!1m1!5f16!2i20!2m3!1m1!5f14!2i30!2m3!1m1!5f15!2i5!2m3!1m1!7f360!2i100!2m3!1m1!7f45!2i50!2m3!1m1!5f13!2i30!2m4!1m2!3f47.5!4f-122.1!2i50!3b1!9b1",basic:"!1m5!1i800!2i600!3f47.651316!4f-122.353048!5f15!2m4!1m2!3f47.75!4f-122.35!2i50!2m4!1m2!3f47.75!4f-122.25!2i50!2m4!1m2!3f47.65!4f-122.25!2i50!2m4!1m2!3f47.65!4f-122.35!2i50!2m4!1m2!3f47.7!4f-122.3!2i50!2m3!1m1!5f16!2i20!2m3!1m1!5f14!2i30!2m3!1m1!5f15!2i5!2m3!1m1!7f360!2i100!2m3!1m1!7f45!2i50!2m3!1m1!5f13!2i30!2m4!1m2!3f47.5!4f-122.1!2i50!3b1!9b1"};var LD={Transit:"!2m1!2sm!2m2!1e2!2stransit!3m5!12m4!1e68!2m2!1sset!2sTransitFocused",TrafficIncidents:"!2m1!2sm!2m11!1e2!2straffic!4m2!1sincidents!2s1!4m2!1sincidents_text!2s1!4m2!1soffset_polylines!2s0!3m5!12m4!1e68!2m2!1sset!2sRoadmap",Terrain:"!2m2!1e4!2st!2m2!1e0!2sm!3m5!12m4!1e68!2m2!1sset!2sTerrain",Spotlight:"!2m1!2sm!2m11!1e2!2sspotlight!7b0!8m7!2m6!1s0x6b12ae19fd46b025:0xfa7c1eadc6105df0!2sSticky Bar, Sydney!4m2!3d-33.880637!4d151.21542499999998!5e0!3m5!12m4!1e68!2m2!1sset!2sRoadmap",Hybrid:"!2m1!2sh!3m5!12m4!1e68!2m2!1sset!2sRoadmapSatellite", +GlobeSpotlight:"!2m5!1e0!2sm!4m2!1sgm!2s0!2m11!1e2!2sspotlight!7b0!8m7!2m6!1s0x6b12ae19fd46b025:0xfa7c1eadc6105df0!2sSticky Bar, Sydney!4m2!3d-33.880637!4d151.21542499999998!5e0!3m5!12m4!1e68!2m2!1sset!2sRoadmapSatellite",GlobeScreen:"!2m5!1e0!2sm!4m2!1sgm!2s2!3m5!12m4!1e68!2m2!1sset!2sRoadmapSatellite",GlobeNoStyler:"!2m5!1e0!2sm!4m2!1sgm!2s0",GlobeDirectionsSpotlight:"!2m5!1e0!2sm!4m2!1sgm!2s0!2m35!1e2!2sspotlight!8m32!8m27!1m2!1sSeattle,+WA!12sjyFgHHybFbea1URpRmUlEFUz6JMsEJBU!1m2!1sKirkland,+WA!12sG55rHEdtKLdXKHhwqmp3envOUijAEpBU!4i0!6m18!1m1!8e2!2m1!20e3!4b1!6m9!1b1!2i0!3i0!4b1!7i1!9s!17b0!18b0!20i-1!16b1!19m1!3j1431032589!21sSCOrXqvXCksiVzgESAmlsHSqQW9glSXfGVA==,NC-4RRbxusWK9rYm!13m3!18m1!9b1!22m0!3m5!12m4!1e68!2m2!1sset!2sRoadmapSatellite", +Globe:"!2m5!1e0!2sm!4m2!1sgm!2s0!3m5!12m4!1e68!2m2!1sset!2sRoadmapSatellite",GeocodeSpotlight:"!2m1!2sm!2m17!1e2!2sspotlight!8m14!2m7!1s0xc42e3783261bc8b:0xa6ec2c940768a3ec!2sSpain!4m2!3d40.4167515!4d-3.7038639!5e1!6b1!13m3!18m1!9b1!22m0!14b1!19u4!3m5!12m4!1e68!2m2!1sset!2sRoadmap",DirectionsSpotlight:"!2m1!2sm!2m35!1e2!2sspotlight!8m32!8m27!1m2!1sSeattle,+WA!12sjyFgHHybFbea1URpRmUlEFUz6JMsEJBU!1m2!1sKirkland,+WA!12sG55rHEdtKLdXKHhwqmp3envOUijAEpBU!4i0!6m18!1m1!8e2!2m1!20e3!4b1!6m9!1b1!2i0!3i0!4b1!7i1!9s!17b0!18b0!20i-1!16b1!19m1!3j1431032589!21sSCOrXqvXCksiVzgESAmlsHSqQW9glSXfGVA==,NC-4RRbxusWK9rYm!13m3!18m1!9b1!22m0!3m5!12m4!1e68!2m2!1sset!2sRoadmap", +DiffTileRemove:"!2m2!1e0!2sm!2m14!1e2!2sindoor!4m2!1slv!2s0x54901506e5106033:0x40a98c0503df27bc!4m2!1srs!2s1!4m2!1slv_hl!2s1!4m2!1srv_il!2s1!3m5!12m4!1e68!2m2!1sset!2sRoadmap",Default:"!2m1!2sm!3m5!12m4!1e68!2m2!1sset!2sRoadmap",Bike:"!2m1!2sm!2m2!1e2!2sbike!3m5!12m4!1e68!2m2!1sset!2sNonRoadmap",BasemapTransitTraffic:"!2m1!2sm!2m8!1e2!2straffic!4m2!1sincidents!2s1!4m2!1sincidents_text!2s1!3m5!12m4!1e68!2m2!1sset!2sRoadmapMuted",AdsSpotlight:"!2m3!1e0!2sm!3i301074684!2m77!1e2!2sspotlight!8m74!5m27!2m26!4m12!1m4!1i678488253!2i1!3i0!4e0!2m2!3d37.797237!4d-122.436386!3sDentist in san francisco!4sUnion Street Dental Care Offers Affordable Dental!8i2!12e1!4m12!1m4!1i678488253!2i2!3i0!4e0!2m2!3d37.774081!4d-122.50992!3sAffordable Dental Care!4sAffordable General Dentistry. Call Our San Francis!8i3!12e1!12m41!1sdentist!2m2!1s115968771510351694523!2s2a!3m1!3s0x0:0xe103b2b26035a543!3m1!3s0x0:0xad881c743179cb66!3m1!3s0x0:0xb27c54dbda21965e!3m1!3s0x0:0x21266dfd418dac5a!3m1!3s0x0:0xeaa34ede4d366944!3m1!3s0x0:0xde096013c05cc519!3m1!3s0x0:0x81397e9d42c0d33f!3m1!3s0x0:0x2a9386dadae6e2d!3m1!3s0x0:0x9621b25de6467250!3m1!3s0x0:0x2d77bcbfe02df96f!5ssan francisco!8m6!3m2!3d37.703399999999995!4d-122.527!4m2!3d37.812!4d-122.34819999999999!10b0!13m7!1s0x80859a6d00690021:0x4a501367f076adff!2sdentist in san francisco!4m2!3d37.7749295!4d-122.4194155!5e1!6b1!13m2!18m1!9b1!19u4!3m5!12m4!1e68!2m2!1sset!2sRoadmap"};function MD(a){this.data=a||[]}var ND;F(MD,W);function OD(a){this.data=a||[]}var PD;F(OD,W);function QD(a){this.data=a||[]}var RD;F(QD,W);function SD(a){this.data=a||[]}var TD;F(SD,W);function UD(a){this.data=a||[]}var VD;F(UD,W);function WD(a){this.data=a||[]}var XD;F(WD,W);function YD(a){this.data=a||[]}var ZD;F(YD,W);function $D(a){this.data=a||[]}var aE;F($D,W);function bE(a){this.data=a||[]}var cE;F(bE,W);function dE(a){this.data=a||[]}var eE;F(dE,W);function fE(a){this.data=a||[]}var gE;F(fE,W);function hE(a){this.data=a||[]}var iE; +F(hE,W);function jE(a){this.data=a||[]}var kE;F(jE,W);function lE(a){this.data=a||[]}var mE;F(lE,W);function nE(a){this.data=a||[]}var oE;F(nE,W);function pE(a){this.data=a||[]}var qE;F(pE,W);function rE(a){this.data=a||[]}var sE;F(rE,W);function tE(a){this.data=a||[]}var uE;F(tE,W); +function vE(){if(!PD){var a=PD={a:-1,F:[]},b=new QD([]);RD||(RD={a:-1,F:[]},RD.F=[,R,ae(256)]);b=V(b,RD);var c=new SD([]);TD||(TD={a:-1,F:[]},TD.F=[,ae(88),ae(120),ae(12),ae(1),ge(!0),T]);c=V(c,TD);var d=Zd(1),e=new UD([]);VD||(VD={a:-1,F:[]},VD.F=[,R,P,ae(256)]);e=V(e,VD);var f=new WD([]);XD||(XD={a:-1,F:[,ie]});a.F=[,T,b,c,R,d,R,e,V(f,XD),R]}return PD} +function wE(){var a=[];ZD={a:-1,F:a};a[1]=T;a[28]=T;a[2]=P;a[44]=T;a[8]=T;a[16]=T;a[11]=T;a[1021]=ge(!0);a[43]=R;a[7]=R;a[17]=R;a[18]=ge(!0);a[21]=R;a[22]=ce;var b=new hE([]);iE||(iE={a:-1,F:[,R,R,R,R,R,R,R,R,P]});a[26]=V(b,iE);b=new fE([]);gE||(gE={a:-1,F:[,R]});a[59]=V(b,gE);b=new $D([]);aE||(aE={a:-1,F:[]},aE.F=[,Zd(1)]);a[30]=V(b,aE);a[32]=ge(!0);a[36]=R;a[41]=ie;a[42]=ce;a[58]=R;a[33]=T;a[5]=R;a[6]=ge(!0);a[9]=R;a[14]=R;a[29]=R;a[40]=R;a[38]=he(1);a[50]=T;a[10]=R;b=new bE([]);cE||(cE={a:-1,F:[]}, +cE.F=[,T,T,,V(new OD([]),vE())]);a[19]=V(b,cE);b=new dE([]);eE||(eE={a:-1,F:[]},eE.F=[,T,T,V(new OD([]),vE())]);a[20]=V(b,eE);a[25]=R;a[48]=R;a[45]=R;a[51]=he(1);a[52]=P;a[54]=T;a[39]=R;a[57]=R;a[62]=ce;a[63]=ce;a[46]=R;a[60]=R;a[61]=R;a[64]=R;a[65]=R;a[1024]=R;a[12]=ge(!0);a[13]=R;a[15]=R;a[34]=R;a[4]=R;a[24]=R;a[47]=R};function xE(a){this.data=a||[]}var yE;F(xE,W);function oC(a){this.data=a||[]}var zE;F(oC,W);function AE(a){this.data=a||[]}var BE;F(AE,W);function CE(a){this.data=a||[]}var DE;F(CE,W);function EE(a){this.data=a||[]}var FE;F(EE,W);function GE(a){this.data=a||[]}var HE;F(GE,W);function IE(a){this.data=a||[]}var JE;F(IE,W);function KE(a){this.data=a||[]}var LE;F(KE,W);function ME(a){this.data=a||[]}var NE;F(ME,W);function OE(a){return new Oz(Ae(a,0))}EE.prototype.clearRect=function(){Be(this,2)};IE.prototype.getZoom=function(){return X(this,2)};KE.prototype.getZoom=function(){return X(this,1)};function PE(){NE||(NE={a:-1,F:[,de,de]});return NE};function QE(a){this.data=a||[]}var RE;F(QE,W); +function SE(){if(!RE){var a=RE={a:-1,F:[]};if(!FE){var b=[];FE={a:-1,F:b};b[1]=V(new Oz([]),Qz());var c=new GE([]);HE||(HE={a:-1,F:[,P,P]});b[6]=V(c,HE);c=new AE([]);BE||(BE={a:-1,F:[]},BE.F=[,V(new Oz([]),Qz()),P,re]);b[8]=V(c,BE);c=new IE([]);JE||(JE={a:-1,F:[]},JE.F=[,V(new ME([]),PE()),V(new ME([]),PE()),P]);b[3]=V(c,JE);c=new KE([]);LE||(LE={a:-1,F:[]},LE.F=[,V(new ME([]),PE()),Q,V(new ne([]),oe()),pe(oe()),V(new ne([]),oe()),V(new ne([]),oe()),Q,Vd("u",17)]);b[4]=V(c,LE);b[25]=U;c=new CE([]); +DE||(DE={a:-1,F:[]},DE.F=[,Vd("d",1),Yd,Yd,Vd("d",1),Yd,Yd]);b[1001]=V(c,DE)}b=pe(FE);if(!Pn){c=Pn={a:-1,F:[]};Rn||(Rn={a:-1,F:[,je,U]});var d=pe(Rn),e=new $k([]);if(!al){var f=al={a:-1,F:[]};bl||el();var g=pe(bl);cl||fl();var h=pe(cl);dl||gl();f.F=[,g,h,ie,pe(dl)]}c.F=[,T,U,P,d,ce,V(e,al),R,V(new Bn([]),Nn())]}c=pe(Pn);d=new oC([]);zE||(e=zE={a:-1,F:[]},f=new xE([]),yE||(yE={a:-1,F:[,P,P]}),f=V(f,yE),Tn||(Tn={a:-1,F:[]},g=Wd("e",37),h=Tn,Vn||Wn(),h.F=[,g,pe(Vn)]),e.F=[,,U,U,R,T,,f,,,,,pe(Tn),Q,, +U,R,R,R]);d=V(d,zE);e=V(new OD([]),vE());f=new YD([]);ZD||wE();f=V(f,ZD);g=Vd("v","");h=new jE([]);kE||(kE={a:-1,F:[,T,Yd,Yd,P,U,U,U]});h=V(h,kE);var k=new lE([]);mE||(mE={a:-1,F:[]},mE.F=[,T,ge(!0)]);k=V(k,mE);var l=new nE([]);oE||(oE={a:-1,F:[]},oE.F=[,T,R,Zd(1),R,R]);l=V(l,oE);var m=new pE([]);qE||(qE={a:-1,F:[,R]});m=V(m,qE);var n=new MD([]);ND||(ND={a:-1,F:[]},ND.F=[,,he(1),R,,,R,T,R,R,ae(-1),P,P,U,,R]);n=V(n,ND);var p=Vd("j",""),q=new tE([]);uE||(uE={a:-1,F:[,R,T]});q=V(q,uE);var t=new rE([]); +sE||(sE={a:-1,F:[]},sE.F=[,R,ge(!0),R,ge(!0),R,R]);a.F=[,b,c,d,T,e,f,U,g,h,,k,l,P,R,R,R,,m,R,n,p,q,ce,V(t,sE),P]}return RE}function TE(a){return new oC(Ae(a,2))}function mC(a,b){return new On(Ee(a,1,b))}function UE(a){return new On(De(a,1))};function VE(a){var b=new QE,c=LD[a];if(!B(c))throw Error("Unknown template: "+a);var d;if(d=c)d=SE(),d=!qs.a(c,b.data,d);if(d)throw Error("Failed to parse template:"+a);for(a=0;a<Fe(b,1);a++)c=mC(b,a),xe(c,7)&&(c=new Bn(c.data[7]),xe(c,7)&&(c=new wn(c.data[7]),xe(c,5)&&Be(new Fm(c.data[5]),5)));return b};function WE(a,b){Ib.call(this);this.f=b;this.a=[];if(a>this.f)throw Error("[goog.structs.SimplePool] Initial cannot be greater than max");for(b=0;b<a;b++)this.a.push(this.b())}F(WE,Ib);function XE(a,b){a.a.length<a.f?a.a.push(b):a.c(b)}WE.prototype.b=function(){return{}};WE.prototype.c=function(a){if(za(a))if(ya(a.$))a.$();else for(var b in a)delete a[b]};WE.prototype.X=function(){WE.R.X.call(this);for(var a=this.a;a.length;)this.c(a.pop());delete this.a};function YE(){this.a=[];this.f=new aB;this.m=this.o=this.s=this.i=0;this.b=new aB;this.g=this.l=0;this.u=1;this.h=new WE(0,4E3);this.h.b=function(){return new ZE};this.j=new WE(0,50);this.j.b=function(){return new $E};var a=this;this.c=new WE(0,2E3);this.c.b=function(){return String(a.u++)};this.c.c=function(){}}function $E(){this.Ud=this.time=this.count=0} +$E.prototype.toString=function(){var a=[];a.push(this.type," ",this.count," (",Math.round(10*this.time)/10," ms)");this.Ud&&a.push(" [VarAlloc = ",this.Ud,"]");return a.join("")};function ZE(){}function aF(a,b,c,d){var e=[];-1==c?e.push(" "):e.push(bF(a.b-c));e.push(" ",cF(a.b-b));0==a.a?e.push(" Start "):1==a.a?(e.push(" Done "),e.push(bF(a.g-a.startTime)," ms ")):e.push(" Comment ");e.push(d,a);0<a.f&&e.push("[VarAlloc ",a.f,"] ");return e.join("")} +ZE.prototype.toString=function(){return null==this.type?this.c:"["+this.type+"] "+this.c};YE.prototype.Ld=function(){};YE.prototype.reset=function(){for(var a=0;a<this.a.length;a++){var b=this.a[a];b.id&&XE(this.c,b.id);XE(this.h,b)}this.a.length=0;this.f.clear();this.i=E();this.g=this.l=this.m=this.o=this.s=0;a=this.b.nb();for(b=0;b<a.length;b++){var c=this.b.get(a[b]);c.count=0;c.time=0;c.Ud=0;XE(this.j,c)}this.b.clear()}; +YE.prototype.toString=function(){for(var a=[],b=-1,c=[],d=0;d<this.a.length;d++){var e=this.a[d];1==e.a&&c.pop();a.push(" ",aF(e,this.i,b,c.join("")));b=e.b;a.push("\n");0==e.a&&c.push("| ")}if(0!=this.f.c){var f=E();a.push(" Unstopped timers:\n");$A(this.f,function(b){a.push(" ",b," (",f-b.startTime," ms, started at ",cF(b.startTime),")\n")})}b=this.b.nb();for(d=0;d<b.length;d++)c=this.b.get(b[d]),1<c.count&&a.push(" TOTAL ",c,"\n");a.push("Total tracers created ",this.l,"\n","Total comments created ", +this.g,"\n","Overhead start: ",this.s," ms\n","Overhead end: ",this.o," ms\n","Overhead comment: ",this.m," ms\n");return a.join("")};function bF(a){a=Math.round(a);var b="";1E3>a&&(b=" ");100>a&&(b=" ");10>a&&(b=" ");return b+a}function cF(a){a=Math.round(a);return String(100+a/1E3%60).substring(1,3)+"."+String(1E3+a%1E3).substring(1,4)}new YE;function dF(a){Ib.call(this);this.b=a}F(dF,Ib);dF.prototype.a=function(a){return eF(this,a)};function fF(a,b){return(b?"__wrapper_":"__protected_")+(a[Aa]||(a[Aa]=++Ba))+"__"}function eF(a,b){var c=fF(a,!0);b[c]||((b[c]=gF(a,b))[fF(a,!1)]=b);return b[c]} +function gF(a,b){function c(){if(a.O())return b.apply(this,arguments);try{return b.apply(this,arguments)}catch(d){if(!(d&&"object"===typeof d&&d.message&&0==d.message.indexOf("Error in protected function: ")||"string"===typeof d&&0==d.indexOf("Error in protected function: ")))throw a.b(d),new hF(d);}finally{}}c[fF(a,!1)]=b;return c} +function iF(a,b){var c=ra("window"),d=c[b];c[b]=function(b,c){pa(b)&&(b=Ea(Fa,b));arguments[0]=b=eF(a,b);if(d.apply)return d.apply(this,arguments);var e=b;if(2<arguments.length){var f=Array.prototype.slice.call(arguments,2);e=function(){b.apply(this,f)}}return d(e,c)};c[b][fF(a,!1)]=d}dF.prototype.X=function(){var a=ra("window");var b=a.setTimeout;b=b[fF(this,!1)]||b;a.setTimeout=b;b=a.setInterval;b=b[fF(this,!1)]||b;a.setInterval=b;dF.R.X.call(this)}; +function hF(a){Ja.call(this,"Error in protected function: "+(a&&a.message?String(a.message):String(a)));(a=a&&a.stack)&&pa(a)&&(this.stack=a)}F(hF,Ja);function jF(a,b,c){rc.call(this);this.c=b||null;this.b={};this.h=kF;this.g=a;if(!c)if(this.a=null,pb&&!Ab("10"))Db(D(this.f,this));else{this.a=new dF(D(this.f,this));iF(this.a,"setTimeout");iF(this.a,"setInterval");a=this.a;b=ra("window");c=["requestAnimationFrame","mozRequestAnimationFrame","webkitAnimationFrame","msRequestAnimationFrame"];for(var d=0;d<c.length;d++){var e=c[d];c[d]in b&&iF(a,e)}a=this.a;Gb=!0;b=D(a.a,a);for(c=0;c<Eb.length;c++)Eb[c](b);Fb.push(a)}}F(jF,rc); +function lF(a,b){Qb.call(this,"a");this.error=a;this.context=b}F(lF,Qb);function kF(a,b,c,d){qD(a,null,b,c,d)}function mF(a,b){return a.a?eF(a.a,b):null} +jF.prototype.f=function(a,b){a=a.error||a;if(b){var c={};for(d in b)c[d]=b[d];b=c}else b={};a instanceof Error&&ib(b,a.__closure__error__context__984382||{});c=ra("window.location.href");if(pa(a))a={message:a,name:"Unknown error",lineNumber:"Not available",fileName:c,stack:"Not available"};else{var d=!1;try{var e=a.lineNumber||a.line||"Not available"}catch(q){e="Not available",d=!0}try{var f=a.fileName||a.filename||a.sourceURL||x.$googDebugFname||c}catch(q){f="Not available",d=!0}a=!d&&a.lineNumber&& +a.fileName&&a.stack&&a.message&&a.name?a:{message:a.message||"Not available",name:a.name||"UnknownError",lineNumber:e,fileName:f,stack:a.stack||"Not available"}}if(this.c)try{this.c(a,b)}catch(q){}f=a.message.substring(0,1900);e=a.stack;try{var g=lB(this.g,"script",a.fileName,"error",f,"line",a.lineNumber);a:{var h=this.b,k;for(k in h){var l=!1;break a}l=!0}if(!l){l=g;var m=kB(this.b);g=hB(l,m)}m={};m.trace=e;if(b)for(var n in b)m["context."+n]=b[n];var p=kB(m);qa(null)&&(p=p.substring(0,null));this.h(g, +"POST",p,this.i)}catch(q){}try{this.dispatchEvent(new lF(a,b))}catch(q){}};jF.prototype.X=function(){Lb(this.a);jF.R.X.call(this)};function nF(a){var b=a[Aa]||(a[Aa]=++Ba),c=Error();c.message="~#!#~"+b+"~#!#~"+a.message+"~#!#~";throw c;};function oF(a,b){a.imageSmoothingEnabled=b;a.mozImageSmoothingEnabled=b;a.webkitImageSmoothingEnabled=b;a.msImageSmoothingEnabled=b}function pF(a,b){2==a&&zc?(0>=qF&&(qF=go("canvas").getContext("2d").webkitBackingStorePixelRatio||1),a=b/qF):a=b;return a}var qF=-1;function rF(a,b){this.i=a;this.l=[];this.j=b;this.a=!1;this.h=this.b=0;this.f=this.c=this.id=this.g=-1}rF.prototype.cancel=function(){this.a=!0};function sF(){this.j=this.m=this.l=this.o=this.C=0}sF.prototype.u=function(a){var b=this.C+a.C;this.o+=a.o;this.m+=a.m;this.l=Math.max(this.l,a.l);this.j=Math.max(this.j,a.j);this.C=b};function tF(){this.a=[];this.b=[]}function uF(a){0==a.a.length&&(a.a=a.b,a.a.reverse(),a.b=[])}function vF(a){return 0==a.a.length&&0==a.b.length}tF.prototype.clear=function(){this.a=[];this.b=[]};tF.prototype.ob=function(){for(var a=[],b=this.a.length-1;0<=b;--b)a.push(this.a[b]);var c=this.b.length;for(b=0;b<c;++b)a.push(this.b[b]);return a};function wF(){this.a={};this.b=this.c=void 0}function xF(a,b,c){c=Math.floor(c);a.a[c]||(a.a[c]=new tF);a.a[c].b.push(b);if(!B(a.c)||c<a.c)a.c=c;if(!B(a.b)||c>a.b)a.b=c}function yF(a){(a=zF(a))?(uF(a),a=a.a.pop()):a=void 0;return a}function AF(a){if(!B(a.b))return-1;for(var b=a.b;b>=a.c;b--)if(a.a[b]&&!vF(a.a[b]))return b;return-1}function BF(a){(a=zF(a))?(uF(a),a=a.a,a=a[a.length-1]):a=void 0;return a} +function zF(a){if(!B(a.b))return null;for(var b=a.b;b>=a.c;b--)if(a.a[b]&&!vF(a.a[b]))return a.a[b];return null};function CF(a,b){this.h=new sF;for(var c=0;c<a.length;c++){var d=a[c];d.id=c;d.webkitPostMessage&&(d.postMessage=d.webkitPostMessage);d.addEventListener("message",D(this.o,this),!1)}this.i=10*a.length;this.b=a;this.s=new wF;this.c=Array(this.b.length);for(c=0;c<this.b.length;c++)this.c[c]=0;this.g={};this.a=this.j=this.f=0;this.l=b||sa}function DF(a){a=a();for(var b=Array(1),c=0;c<b.length;c++)b[c]=new Worker(a);return new CF(b,void 0)} +CF.prototype.m=function(){var a=this.h,b=new sF;b.C=a.C;b.o=a.o;b.l=a.l;b.m=a.m;b.j=a.j;this.h=new sF;return b};function EF(a,b){b.c=E();FF(a,b,a.a);a.a=(a.a+1)%a.b.length}function GF(a){for(;a.f<a.i;){var b=a.a;if(10>a.c[b]){var c=yF(a.s);if(!B(c))break;FF(a,c,b)}a.a=(a.a+1)%a.b.length}}function FF(a,b,c){if(!b.a){var d=a.j++;b.id=d;b.f=c;var e=b.i,f=b.l,g={};g.id=d;g.command=1;g.payload=e;a.b[c].postMessage(g,f);e=E()-b.c;b.h=e;a.g[d]=b;a.c[c]++;a.f++}} +CF.prototype.o=function(a){var b=a.data.id,c=a.data.payload,d=a.data.logs,e=a.data.complete,f=a.data.time;a=a.data.received;if(d)for(var g=0;g<d.length;g++)this.l(d[g]);B(b)&&(d=this.g[b])&&(d.b+=f,a&&(d.g=a-(d.c+d.h)),e&&(f=this.h,a=d.g,g=d.b,f.o+=a,f.m+=g,a>f.l&&(f.l=a),g>f.j&&(f.j=g),f.C++,delete this.g[b],this.c[d.f]--,this.f--,GF(this)),d.a||d.j(c,e))}; +CF.prototype.abort=function(a){a.cancel();if(!(0>a.id)){var b={};b.abort=a.id;var c=a.f;this.b[c].postMessage(b);this.c[c]--;this.f--;delete this.g[a.id];GF(this)}};function HF(a){this.data=a||[]}F(HF,W);function IF(){var a=JF.sc();return!!ye(a,0,void 0)};function JF(a){this.data=a||[]}F(JF,HF);ta(JF);function KF(a){this.b=a.toString();a="";var b=this.b.indexOf("?");0<=b&&(a=this.b.substring(b+1),this.b=this.b.substring(0,b));this.c=a?"&"+a:"";1<this.b.length&&"/"!=this.b[this.b.length-1]&&(this.b+="/")}KF.prototype.a=function(a){"/"==a[0]&&(a=a.slice(1));return this.b+a+this.c};function LF(){this.G=!0;this.T=this.u=!1;this.L=5;this.s=null;this.la=1;this.v=this.j=["//www.google.com/maps/vt"];this.l=[];this.ga=this.fa=this.I=!0;this.U=["/kh?v=0"];this.ia=["//mt0.google.com/vt?lyrs=t"];this.O=["/vt/stream"];this.K=["/vt"];this.P={};this.C=69;this.c=1;this.B=!1;this.h=null;this.m=!1;this.Y=this.H=null;this.W=this.M=this.V=this.a=!1;this.J=1;this.A=this.D=null;this.Nb=this.i=!1;this.g=null;this.Z=!0;this.f=0;this.S=!0;this.b=this.viewport=null;var a=JF.sc();this.ja=X(a,14);this.ha= +!!ye(a,4,void 0);this.o=function(){return sa}}function MF(a,b){if(a.P[b])return a.P[b];var c=encodeURIComponent(a.f.toString());b=encodeURIComponent(b);c="st?ep="+c+"&cs="+b+"&fmt=compact";0<a.l.length&&(c+="&expIds="+a.l.join(","));return(new KF(a.j[0])).a(c)}function NF(a){if(!a.b)return 0;var b=1;1==a.c&&(b|=2,a.i&&(b|=4));return b};function OF(){this.l=1024;this.j=768;this.v=this.u=null;this.C=this.A=!1;this.g=x.devicePixelRatio||1;this.f="en";this.c="us";this.b=!0;this.m=new Es(Is.a.slice());this.s=new Js;this.a=new Es(Is.a.slice());this.h=new Js;this.i=2;this.B=!0;this.o=this.D=!1}function PF(a,b){for(var c=[],d=0;d<a.length;d++)c[d]=a[d]+b;return c};function QF(){this.b=!1;this.a=null;this.c=0}var RF=1;QF.prototype.clear=function(){this.b=!1};QF.prototype.wait=function(a,b,c){var d=RF++;if(this.b&&(c?!b.call(c,a):!b(a)))return d;this.a||(this.a=[]);this.a.push({handle:d,qc:b,scope:c});return d};function SF(){this.height=this.width=this.o=this.s=this.a=this.b=this.ta=this.c=this.m=this.l=this.j=this.f=this.i=this.h=this.g=void 0}function TF(a,b){return!!b&&a.g==b.g&&a.h==b.h&&a.i==b.i&&a.f==b.f&&a.j==b.j&&a.l==b.l&&a.m==b.m&&a.c==b.c&&a.ta==b.ta&&a.b==b.b&&a.a==b.a&&a.s==b.s&&a.o==b.o&&a.width==b.width&&a.height==b.height};function UF(a){this.length=a.length||a;for(var b=0;b<this.length;b++)this[b]=a[b]||0}UF.prototype.a=4;UF.prototype.set=function(a,b){b=b||0;for(var c=0;c<a.length&&b+c<this.length;c++)this[b+c]=a[c]};UF.prototype.toString=Array.prototype.join;"undefined"==typeof Float32Array&&(UF.BYTES_PER_ELEMENT=4,UF.prototype.BYTES_PER_ELEMENT=UF.prototype.a,UF.prototype.set=UF.prototype.set,UF.prototype.toString=UF.prototype.toString,Ia("Float32Array",UF));function VF(a){this.length=a.length||a;for(var b=0;b<this.length;b++)this[b]=a[b]||0}VF.prototype.a=8;VF.prototype.set=function(a,b){b=b||0;for(var c=0;c<a.length&&b+c<this.length;c++)this[b+c]=a[c]};VF.prototype.toString=Array.prototype.join;if("undefined"==typeof Float64Array){try{VF.BYTES_PER_ELEMENT=8}catch(a){}VF.prototype.BYTES_PER_ELEMENT=VF.prototype.a;VF.prototype.set=VF.prototype.set;VF.prototype.toString=VF.prototype.toString;Ia("Float64Array",VF)};function WF(){return new Float64Array(3)}function XF(a,b,c,d){a[0]=b;a[1]=c;a[2]=d;return a}function YF(a,b,c){c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2]}function ZF(a,b,c){c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2]}function $F(a,b,c){c[0]=a[0]*b;c[1]=a[1]*b;c[2]=a[2]*b}function aG(a){var b=a[0],c=a[1];a=a[2];return b*b+c*c+a*a}function bG(a,b){var c=a[0],d=a[1];a=a[2];var e=1/Math.sqrt(c*c+d*d+a*a);b[0]=c*e;b[1]=d*e;b[2]=a*e;return b}function cG(a,b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]};function dG(a,b){a[0]=b[0];a[1]=b[1];a[2]=b[2]};function eG(){return new Float64Array(4)}function fG(a,b,c){c[0]=a[0]*b;c[1]=a[1]*b;c[2]=a[2]*b;c[3]=a[3]*b};function gG(){return new Float64Array(16)}function hG(a,b,c,d){var e=-Math.PI,f=Math.PI;a[0]=b;a[1]=0;a[2]=0;a[3]=0;a[4]=0;a[5]=c;a[6]=0;a[7]=0;a[8]=0;a[9]=0;a[10]=d;a[11]=0;a[12]=e;a[13]=f;a[14]=0;a[15]=1}function iG(a,b){a[0]=b[0];a[1]=b[1];a[2]=b[2];a[3]=b[3];a[4]=b[4];a[5]=b[5];a[6]=b[6];a[7]=b[7];a[8]=b[8];a[9]=b[9];a[10]=b[10];a[11]=b[11];a[12]=b[12];a[13]=b[13];a[14]=b[14];a[15]=b[15]}function jG(a,b,c){c[0]=a[b];c[1]=a[b+4];c[2]=a[b+8];c[3]=a[b+12]} +function kG(a,b,c){var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],k=a[5],l=a[6],m=a[7],n=a[8],p=a[9],q=a[10],t=a[11],v=a[12],u=a[13],w=a[14];a=a[15];var y=b[0],A=b[1],z=b[2],C=b[3],I=b[4],S=b[5],ca=b[6],Z=b[7],ha=b[8],ea=b[9],ja=b[10],Y=b[11],ma=b[12],Ga=b[13],wa=b[14];b=b[15];c[0]=d*y+h*A+n*z+v*C;c[1]=e*y+k*A+p*z+u*C;c[2]=f*y+l*A+q*z+w*C;c[3]=g*y+m*A+t*z+a*C;c[4]=d*I+h*S+n*ca+v*Z;c[5]=e*I+k*S+p*ca+u*Z;c[6]=f*I+l*S+q*ca+w*Z;c[7]=g*I+m*S+t*ca+a*Z;c[8]=d*ha+h*ea+n*ja+v*Y;c[9]=e*ha+k*ea+p*ja+u*Y;c[10]=f*ha+ +l*ea+q*ja+w*Y;c[11]=g*ha+m*ea+t*ja+a*Y;c[12]=d*ma+h*Ga+n*wa+v*b;c[13]=e*ma+k*Ga+p*wa+u*b;c[14]=f*ma+l*Ga+q*wa+w*b;c[15]=g*ma+m*Ga+t*wa+a*b} +function lG(a,b){var c=a[0],d=a[1],e=a[2],f=a[3],g=a[4],h=a[5],k=a[6],l=a[7],m=a[8],n=a[9],p=a[10],q=a[11],t=a[12],v=a[13],u=a[14];a=a[15];var w=c*h-d*g,y=c*k-e*g,A=c*l-f*g,z=d*k-e*h,C=d*l-f*h,I=e*l-f*k,S=m*v-n*t,ca=m*u-p*t,Z=m*a-q*t,ha=n*u-p*v,ea=n*a-q*v,ja=p*a-q*u,Y=w*ja-y*ea+A*ha+z*Z-C*ca+I*S;0!=Y&&(Y=1/Y,b[0]=(h*ja-k*ea+l*ha)*Y,b[1]=(-d*ja+e*ea-f*ha)*Y,b[2]=(v*I-u*C+a*z)*Y,b[3]=(-n*I+p*C-q*z)*Y,b[4]=(-g*ja+k*Z-l*ca)*Y,b[5]=(c*ja-e*Z+f*ca)*Y,b[6]=(-t*I+u*A-a*y)*Y,b[7]=(m*I-p*A+q*y)*Y,b[8]=(g*ea- +h*Z+l*S)*Y,b[9]=(-c*ea+d*Z-f*S)*Y,b[10]=(t*C-v*A+a*w)*Y,b[11]=(-m*C+n*A-q*w)*Y,b[12]=(-g*ha+h*ca-k*S)*Y,b[13]=(c*ha-d*ca+e*S)*Y,b[14]=(-t*z+v*y-u*w)*Y,b[15]=(m*z-n*y+p*w)*Y)}function mG(a,b,c){var d=b[0],e=b[1];b=b[2];var f=1/(d*a[3]+e*a[7]+b*a[11]+a[15]);c[0]=(d*a[0]+e*a[4]+b*a[8]+a[12])*f;c[1]=(d*a[1]+e*a[5]+b*a[9]+a[13])*f;c[2]=(d*a[2]+e*a[6]+b*a[10]+a[14])*f} +function nG(a,b){var c=Math.cos(b);b=Math.sin(b);a[0]=1;a[1]=0;a[2]=0;a[3]=0;a[4]=0;a[5]=c;a[6]=b;a[7]=0;a[8]=0;a[9]=-b;a[10]=c;a[11]=0;a[12]=0;a[13]=0;a[14]=0;a[15]=1}function oG(a,b,c,d){a[12]+=a[0]*b+a[4]*c+a[8]*d;a[13]+=a[1]*b+a[5]*c+a[9]*d;a[14]+=a[2]*b+a[6]*c+a[10]*d;a[15]+=a[3]*b+a[7]*c+a[11]*d} +function pG(a,b){var c=a[4],d=a[5],e=a[6],f=a[7],g=a[8],h=a[9],k=a[10],l=a[11],m=Math.cos(b);b=Math.sin(b);a[4]=c*m+g*b;a[5]=d*m+h*b;a[6]=e*m+k*b;a[7]=f*m+l*b;a[8]=c*-b+g*m;a[9]=d*-b+h*m;a[10]=e*-b+k*m;a[11]=f*-b+l*m}function qG(a,b){var c=a[0],d=a[1],e=a[2],f=a[3],g=a[8],h=a[9],k=a[10],l=a[11],m=Math.cos(b);b=Math.sin(b);a[0]=c*m+g*-b;a[1]=d*m+h*-b;a[2]=e*m+k*-b;a[3]=f*m+l*-b;a[8]=c*b+g*m;a[9]=d*b+h*m;a[10]=e*b+k*m;a[11]=f*b+l*m} +function rG(a,b){var c=a[0],d=a[1],e=a[2],f=a[3],g=a[4],h=a[5],k=a[6],l=a[7],m=Math.cos(b);b=Math.sin(b);a[0]=c*m+g*b;a[1]=d*m+h*b;a[2]=e*m+k*b;a[3]=f*m+l*b;a[4]=c*-b+g*m;a[5]=d*-b+h*m;a[6]=e*-b+k*m;a[7]=f*-b+l*m}function sG(a,b){b[0]=a[12];b[1]=a[13];b[2]=a[14]};function tG(a,b,c,d){a=ao(a);b=ao(b);b=Yn(b,-1.48442222974533,1.48442222974533);d[0]=a;a=Math.sin(b);d[1]=.5*Math.log((1+a)/(1-a));d[2]=c/(6371010*Math.cos(b))}function uG(a,b,c,d,e){vG(a,b,c,d,e);d[0]=180*d[0]/Math.PI;d[1]=180*d[1]/Math.PI}function vG(a,b,c,d,e){b=2*Math.atan(Math.exp(b))-Math.PI/2;c=c*(e||6371010)*Math.cos(b);d[0]=a;d[1]=b;d[2]=c}function wG(a){a=ao(a);a=Yn(a,-1.48442222974533,1.48442222974533);return 1/(6371010*Math.cos(a))} +function xG(a,b,c,d){var e=Math.cos(b);c+=6371010;XF(d,c*e*Math.cos(a),c*e*Math.sin(a),c*Math.sin(b))}function yG(a,b,c,d,e){d=(1<<d)/(2*Math.PI);e[0]=(Math.PI+a)*d;e[1]=(Math.PI-b)*d;e[2]=c*d}function zG(a,b,c,d){c=2*Math.PI/(1<<c);d[0]=a*c-Math.PI;d[1]=-b*c+Math.PI;d[2]=0*c};function AG(a,b){this.o=a;this.c=0;this.a=[];this.l=null!=b?b:24;this.m=0;this.b=new wF;this.g=0;this.i={};this.h=-1;this.j=void 0}function BG(a,b){this.b=a;this.a=this.c=this.f=!1;this.priority=b;this.startTime=0}function CG(a){return(a=a.a[0])?a.length:0} +function DG(a,b,c){var d=b.b;if(!d||d.priority!=c){if(d)a:if(b=d,b.f){d=a.b;for(var e=Math.floor(c),f=d.b;f>=d.c;f--){var g;if(g=d.a[f]){g=d.a[f];var h=b;var k=g.a;var l=La(k,h);0<=l?(Array.prototype.splice.call(k,l,1),k=!0):k=!1;g=k||Ta(g.b,h)}if(g){xF(d,b,e);break}}b.priority=c}else{if(b.c){d=0==a.m;e=AF(a.b)<=c;if(c>b.priority||d||e){a.ec(b);a.Uc(b,c);break a}EG(a,b.b)&&FG(a,b,c)}b.a&&(EG(a,b.b),FG(a,b,c))}else d=new BG(b,c),b.b=d,FG(a,d,c);if(0!=a.l&&a.c==a.l)for(b=!1,d=1;d<c;d++){if(a.a[d]&& +0<a.a[d].length)for(e=a.a[d],f=e.length-1;g=e[f];f--)if(g.b.cancel()){b=!0;g.b.b&&a.ec(g);FG(a,g,d);break}if(b)break}a.Ac()}}r=AG.prototype;r.start=function(){for(var a=0;4>a&&this.Wc();++a){var b=this.Be();if(!b)break;GG(this,b)}for(a=3;1<=a&&!(this.a[a]&&0<this.a[a].length);a--);for(b=1;3>=b;b++)if(b<a){var c=this.i[b];if(c&&0<c.length)for(;0<c.length;){var d=c.pop();d.a=!1;this.g+=-1;d.b.cancel();FG(this,d,b)}}if(this.Wc())return this.start;this.j=void 0;return Dr}; +r.Wc=function(){var a=0==this.l||this.c<this.l;return-1!=AF(this.b)&&a};r.Ac=function(){var a=AF(this.b);if(-1!=a){var b=0;2==a?b=1:3==a&&(b=2);B(this.j)?this.j<b&&(this.o.qd(this,b),this.j=b):(this.o.ed(this,b),this.j=b)}};function GG(a,b){a.Uc(b,b.priority);b.b.start(function(){HG(a,b)})}function FG(a,b,c){b.priority=c;IG(a,b,!0);xF(a.b,b,c)}r.Be=function(){for(var a=yF(this.b);a&&!a.f;)a=yF(this.b);if(!a)return null;IG(this,a,!1);return a}; +r.ec=function(a){this.a[a.priority]&&Ta(this.a[a.priority],a);a.c=!1;this.c+=-1;0==this.c&&-1!=this.h&&(x.clearTimeout(this.h),this.h=-1)};r.Uc=function(a,b){this.a[b]?this.a[b].push(a):this.a[b]=[a];a.startTime=E();a.c=!0;this.c+=1;a.priority=b;-1==this.h&&JG(this)}; +function JG(a){a.h=x.setTimeout(function(){if(0<a.c&&-1!=a.h){for(var b=E(),c=[],d=1;3>=d;d++){var e=a.a[d];if(e)for(var f=0;f<e.length;++f){var g=e[f];1E4<=b-g.startTime&&c.push(g)}}for(b=0;b<c.length;++b)d=a,e=c[b],d.ec(e),d.i[e.priority]?d.i[e.priority].push(e):d.i[e.priority]=[e],f=d,e.a=!0,f.g+=1,d.Ac();0<a.c?JG(a):a.h=-1}},1E4)}function HG(a,b){b&&(b.c?a.ec(b):b.a&&(Ta(a.i[b.priority],b),b.a=!1,a.g+=-1),b.b.b=null);a.Ac()} +function EG(a,b){var c=b.b,d=!1;if(c&&(c.c||c.a)){if(b.cancel()||c.a)HG(a,c),d=!0}else c&&c.f&&(IG(a,c,!1),d=!0);d&&(b.b=null);return d}function IG(a,b,c){b.f=c;a.m+=c?1:-1};function KG(a,b){AG.call(this,a,b);this.f=0}F(KG,AG);r=KG.prototype;r.Uc=function(a,b){KG.R.Uc.call(this,a,b);b>this.f&&(this.f=b)};r.ec=function(a){KG.R.ec.call(this,a);a=a.priority;if(a==this.f&&!this.a[a].length){this.f=0;for(var b=a;0<=b;--b)if(this.a[a].length){this.f=b;break}}};r.Be=function(){for(var a=BF(this.b);a&&!a.f;)yF(this.b),a=BF(this.b);if(!a||a.priority<this.f||0==a.priority&&!(0==this.g&&1>CG(this)))return null;yF(this.b);IG(this,a,!1);return a}; +r.Wc=function(){var a=KG.R.Wc.call(this),b=AF(this.b);0==b&&(a=a&&0==this.g&&1>CG(this));return a&&b>=this.f};r.Ac=function(){AF(this.b)<this.f||KG.R.Ac.call(this)};function LG(a,b){this.a=a;this.b=b};function MG(a,b){return new cs(a,b)};function NG(a,b){if(OG){var c=OG;c.c[a]=b;c.b[a]=!1;c.a[a]=[];c.f[a]=!1}else PG.push({id:a,If:b})}Ia("disposeModuleLoader",function(){OG&&OG.$();OG=null});var OG=null,PG=[];function QG(){this.a=this.s=this.h=0}QG.prototype.u=function(a){this.h+=a.h;this.s+=a.s;this.a+=a.a};QG.prototype.m=function(){var a=new QG;a.h=this.h;a.s=this.s;a.a=this.a;return a};function RG(){this.D=this.v=this.A=this.B=0}RG.prototype.u=function(a){this.B+=a.B;this.A+=a.A;this.v+=a.v;this.D+=a.D};RG.prototype.m=function(){var a=new RG;a.B=this.B;a.A=this.A;a.v=this.v;a.D=this.D;return a};function SG(a,b){this.b=a;this.c=b;this.a={}}SG.prototype.clear=function(){this.a={}};function TG(a,b){return null!=b&&0<b&&null!=a.c&&b<a.c?!1:!0};function UG(a,b,c){this.f=a;this.a=0;this.c=!1;this.b=new SG(b,c)}UG.prototype.h=function(a){var b=this.b.a[a.getZoom()];a=b?(b=b[a.a])?b[a.b]||null:null:null;if(null!==a)return this.f.B++,a;this.c=!0;if(this.a)return this.f.v++,this.a;this.f.A++;return null};UG.prototype.g=function(a){for(var b=null,c=!0,d=0;d<a.length;++d){var e=a[d];null!==e&&-1!=e&&(null===b||e>=b)&&(b=e);-1!=e&&(c=!1)}c&&(b=-1);return b}; +UG.prototype.i=function(a,b,c){if(!(b&&b>c)){b=this.b;var d=a.getZoom();b.a[d]||(b.a[d]={});d=b.a[d];var e=a.a;d[e]||(d[e]={});a=a.b;d=d[e];TG(b,c)&&(null!=c?(B(d[a])?b.b.s++:b.b.h++,d[a]=c):d[a]&&delete d[a]);this.c=!1;TG(this.b,c)&&c>this.a&&(this.a=c)}}; +UG.prototype.j=function(a){var b=this.b,c=new Oz(a.data[1]),d=X(c,1),e=X(c,2),f=c.getZoom();c=Ce(a,3);var g=X(a,2),h=c.length/g;b.a[f]||(b.a[f]={});f=b.a[f];for(var k=0;k<h;++k){var l=e+k;f[l]||(f[l]={});l=f[l];for(var m=0;m<g&&k*g+m<c.length;++m){var n=d+m,p=c[k*g+m];TG(b,p)&&(B(l[n])?b.b.s++:b.b.h++,l[n]=p)}}a=Ce(a,3);for(b=0;b<a.length;++b)TG(this.b,a[b])&&a[b]>this.a&&(this.a=a[b]);0<a.length&&(this.c=!1)};function VG(){this.a={};this.b={};this.c=new QG;this.f=new RG}function WG(a){for(var b in a.a)if(a.a[b].a.c)return!0;return!1}function XG(a,b){this.c=a;this.a=b;this.b=0};/* + Portions of this code are from MochiKit, received by + The Closure Authors under the MIT license. All other code is Copyright + 2005-2009 The Closure Authors. All Rights Reserved. +*/ +function YG(a,b){this.g=[];this.s=a;this.o=b||null;this.f=this.a=!1;this.c=void 0;this.l=this.u=this.i=!1;this.h=0;this.b=null;this.j=0}YG.prototype.cancel=function(a){if(this.a)this.c instanceof YG&&this.c.cancel();else{if(this.b){var b=this.b;delete this.b;a?b.cancel(a):(b.j--,0>=b.j&&b.cancel())}this.s?this.s.call(this.o,this):this.l=!0;this.a||(a=new ZG(this),$G(this),aH(this,!1,a))}};YG.prototype.m=function(a,b){this.i=!1;aH(this,a,b)};function aH(a,b,c){a.a=!0;a.c=c;a.f=!b;bH(a)} +function $G(a){if(a.a){if(!a.l)throw new cH(a);a.l=!1}}YG.prototype.qc=function(a){$G(this);aH(this,!0,a)};function dH(a,b,c){a.g.push([b,c,void 0]);a.a&&bH(a)}YG.prototype.then=function(a,b,c){var d,e,f=new WC(function(a,b){d=a;e=b});dH(this,d,function(a){a instanceof ZG?f.cancel():e(a)});return f.then(a,b,c)};UC(YG);function eH(a){return Pa(a.g,function(a){return ya(a[1])})} +function bH(a){if(a.h&&a.a&&eH(a)){var b=a.h,c=fH[b];c&&(x.clearTimeout(c.a),delete fH[b]);a.h=0}a.b&&(a.b.j--,delete a.b);b=a.c;for(var d=c=!1;a.g.length&&!a.i;){var e=a.g.shift(),f=e[0],g=e[1];e=e[2];if(f=a.f?g:f)try{var h=f.call(e||a.o,b);B(h)&&(a.f=a.f&&(h==b||h instanceof Error),a.c=b=h);if(VC(b)||"function"===typeof x.Promise&&b instanceof x.Promise)d=!0,a.i=!0}catch(k){b=k,a.f=!0,eH(a)||(c=!0)}}a.c=b;d&&(h=D(a.m,a,!0),d=D(a.m,a,!1),b instanceof YG?(dH(b,h,d),b.u=!0):b.then(h,d));c&&(b=new gH(b), +fH[b.a]=b,a.h=b.a)}function cH(a){Ja.call(this);this.a=a}F(cH,Ja);cH.prototype.message="Deferred has already fired";cH.prototype.name="AlreadyCalledError";function ZG(a){Ja.call(this);this.a=a}F(ZG,Ja);ZG.prototype.message="Deferred was canceled";ZG.prototype.name="CanceledError";function gH(a){this.a=x.setTimeout(D(this.c,this),0);this.b=a}gH.prototype.c=function(){delete fH[this.a];throw this.b;};var fH={};function hH(a){return iH&&qa(iH[a])?iH[a]:null}var iH=null;function jH(){if(!x.Worker||null==Xn())return!1;var a=new ArrayBuffer(1);var b=[];var c=x.BlobBuilder||x.WebKitBlobBuilder;if(B(c)){c=new c;for(var d=0;d<b.length;d++)c.append(b[d],void 0);b=c.getBlob("text/javascript")}else if(B(x.Blob))b=new Blob(b,{type:"text/javascript"});else throw Error("This browser doesn't seem to support creating Blobs");c=Xn();if(null==c)throw Error("This browser doesn't seem to support blob URLs");b=c.createObjectURL(b);try{var e=new Worker(b)}catch(f){return!1}e.postMessage(a, +[a]);e.terminate();return 0==a.byteLength};function kH(){if(x.location)return!1;var a=hH("worker");null===a&&(a=hH("workers"));if(0===a)a=!1;else if(1===a)a=!0;else if(a=(!uc||Ab(37))&&jH()&&null!=Xn())(a=x.location)?(new mB(a),a=!1):a=!0;return a};function lH(a,b,c){Pp.call(this);this.b=a;this.s=b;this.g=new so(b.a,void 0,!1);this.o=c;a=go("canvas");this.o.appendChild(a);this.h=this.b.i||2;2==this.h&&(a.style.position="absolute");this.i=new io(a);a=this.h;b=this.i;c=this.b.g;var d=this.b.l,e=this.b.j;try{var f=b.a,g=pF(a,c),h=Math.max(d*g,1),k=Math.max(e*g,1);yc||pb?(h=Math.round(h),k=Math.round(k)):(h=Math.floor(h),k=Math.floor(k));if(f.width!==h||f.height!==k||b.c!==c)b.c=c,f.width=h,f.height=k,f.style.width=d+"px",f.style.height=e+"px"}catch(l){f= +Error(),f.message="setCanvasSize: Error accessing canvas.",nF(f)}if(1==a){g=new wo;g.h=this.b.B;g.i=this.b.D;g.g=this.b.o;g.a=!0;g.f=!0;g.c=!0;g.b=4096;f=this.i;g=g||new wo;h=void 0;g.g&&(h=MG);g=Bo(f.a,g,h);if(!g)throw Error("Could not find a 3d context, error: "+Ao);f=new eq(f,g);Qp(this,f);f=new LG(f,null)}else if(2==a){f=this.i.a;g=null;f.getContext&&(g=f.getContext("2d"));f=g;if(!f)throw Error("Could not create 2D context.");f=new LG(null,f)}else throw Error("Unsupported context type");this.j= +f;this.a=this.l=this.c=this.f=null;this.m=new QF}F(lH,Pp);function mH(a){if(!a.a)throw Error("Not initialized.");return a.a}r=lH.prototype;r.Bf=function(a){a&&a()}; +function nH(a,b,c){if(!OG)throw Error("Module loader requested but none has been injected.");var d=OG;c=D(a.Hf,a,b,c);var e=D(d.h,d,1,D(a.rf,a,c,b)),f=kH(),g=!b.b;f&&g&&(b.b=DF(function(){return null.toString()}));e();oH(d,1);b=a.h;if(1==b)oH(d,2),b=3;else if(2==b)b=4;else throw Error("Unsupported context type");d.h(b,D(a.sf,a,c));oH(d,b)}r.rf=function(a,b){var c=this.s.a;this.c=new pH(b,c,new KG(c,0));a()};r.sf=function(a,b,c){this.l=c.a();a()}; +r.Hf=function(a,b){if(this.c&&this.l){var c=this.l,d=this.j,e=this.i,f=this.g,g=this.c,h=new qH,k=new rH;k=new sH(k,a.i,a.viewport||void 0);var l=a.I;k.h!=l&&(k.h=l,tH(k));1!=k.o&&(k.o=!0,tH(k));1!=k.m&&(k.m=!0,tH(k));uH(k,a.i);l=e.a;var m=e.c,n=vH(k);n.width=Math.ceil(l.width/m);n.height=Math.ceil(l.height/m);wH(k,n);l=new xH(new yH(g.oc));this.a=c.a(a,d,e,h,k,g,l,l,f,void 0);a=this.a.b;var p;c=this.b;d=this.f||void 0;e=c.s;f=c.m;c.b&&c.a.a.length<f.a.length&&Gs(c.a.a[0],f.a[0])&&(p=new Os(c.h,c.a, +c.f,c.c,d));p=new Os(e,f,c.f,c.c,d,p);Ps(a.B,p)||(a.B=p,tH(a));zH(this);this.a.h();p=this.g;p.a=this.a;uo(p);b()}};function zH(a){AH(mH(a).b.a,function(){var b=a.m;if(!b.b&&b.a){b.b=!0;b.c+=1;try{for(var c=0,d=b.a.length;c<d;c++){var e=b.a[c],f=!1;if(e)if(e.scope)f=e.qc.call(e.scope,a);else{var g=e.qc;f=g(a)}f||(1==b.c?(b.a.splice(c,1),--c,--d):b.a[c]=null)}}finally{--b.c}}b.b=!1})}r.X=function(){this.g.$();this.a&&this.a.$();this.a=null;this.c&&this.c.$();this.c=null;lH.R.X.call(this)};function BH(){this.a=this.b=this.c=0};function CH(a,b){this.G=0;this.u=!!a;this.K=b;this.I=a?D(this.Nd,this):sa;this.s=!1;a=document;this.v=(this.b=!(a.hidden||a.webkitHidden||a.mozHidden||a.msHidden))?0:E()+5E3;lo(D(this.M,this));E();this.h=!1;this.i=[];this.f=[];this.g=[];this.a=[];this.a[0]=[];this.a[1]=[];this.a[2]=[];this.a[3]=[];this.a[4]=[];this.a[5]=[];this.D=[];this.J=new BH;this.m=this.l=!1;var c=this;this.L=function(){c.l=!1;c.zc()};this.B=function(){c.m=!1;c.xb()};this.O=x.requestAnimationFrame||x.webkitRequestAnimationFrame|| +x.mozRequestAnimationFrame||x.oRequestAnimationFrame||x.msRequestAnimationFrame;Er.push(this)}function DH(a){a.s||(a.s=!0,x.requestIdleCallback(a.I))}r=CH.prototype;r.Nd=function(a){for(;this.s;){this.s=!1;for(var b=!0;a.timeRemaining()>=this.K;){try{var c=EH(this,!0)}catch(d){c=!0}if(!c){b=!1;break}}if(b){DH(this);break}}};r.Te=function(a){this.i.push(a);this.c()};r.Pd=function(a){this.f.push(a);this.c()};r.Ue=function(a){this.g.push(a);this.c()};r.Mb=function(a,b){FH(this,a,GH(b,!1))}; +r.ed=function(a,b){FH(this,a,GH(b,!0))};function GH(a,b){a*=2;b&&(a+=1);return a}function FH(a,b,c){var d=b.__maps_realtime_JobScheduler_next_step;d&&d!=Dr||(b.__maps_realtime_JobScheduler_next_step=b.start,b.__maps_realtime_JobScheduler_priority=c,a.a[c].push(b),a.u?DH(a):a.h||HH(a))}r.Pe=function(a){a.__maps_realtime_JobScheduler_next_step=null}; +r.qd=function(a,b){if(a.__maps_realtime_JobScheduler_next_step){var c=a.__maps_realtime_JobScheduler_priority;b=1==c||3==c||5==c?GH(b,!0):GH(b,!1);if(c!=b){for(var d=this.a[c].length,e=0;e<d;++e)if(this.a[c][e]==a){this.a[c][e]=null;break}a.__maps_realtime_JobScheduler_priority=b;this.a[b].push(a)}}};r.zc=function(){EH(this,!1)};function EH(a,b){a.h=!0;var c=!1,d=E();try{for(var e=5;0<=e;){if(IH(a,e,b)){if(c=!0,b)break}else e--;if(!b&&1<=E()-d)break}}finally{E(),a.h=!1,a.u||JH(a)}return c} +r.xb=function(){var a=E();this.h=!0;var b=0,c=this.D;if(0<c.length){for(b=0;b<c.length;b++)this.Mb(c[b].Df,c[b].priority);this.D=[]}try{E();var d=this.i;this.i=[];var e=d.length;for(c=0;c<e;c++){var f=d[c];KH();Mr(f)}E();var g=0<this.g.length||0<this.f.length;if(this.b){var h=this.J;d=g;var k=a-h.a;0<h.a&&(h.c++,h.b+=k);h.a=a;d||(h.a=0)}if(0==this.G%1){if(this.b){E();var l=this.f;this.f=[];var m=l.length;for(a=0;a<m;a++){var n=l[a];KH();Qr(n)}E()}E();var p=this.g;this.g=[];var q=p.length;for(l=0;l< +q;l++){var t=p[l];KH();vo(t)}E()}E();for(b=5;0<=b&&!IH(this,b,!0);b--);}finally{E(),this.h=!1,g&&this.b&&this.c(),this.u||JH(this),this.G++}};function JH(a){for(var b=!1,c=0;5>=c;c++)b|=0<a.a[c].length;b&&HH(a)}Hb(function(a){CH.prototype.xb=a(CH.prototype.xb);CH.prototype.zc=a(CH.prototype.zc);CH.prototype.Nd=a(CH.prototype.Nd)}); +function IH(a,b,c){var d=!1,e=a.a[b];if(0==e.length)return d;for(var f=E(),g=0;g<e.length;g++){var h=e[g];if(h){var k=h.__maps_realtime_JobScheduler_next_step;if(k){for(;k!=Dr&&0==E()-f;){d=!0;KH();k=Dr;try{k=h.__maps_realtime_JobScheduler_next_step()}finally{h.__maps_realtime_JobScheduler_next_step=k}if(c)break}k==Dr&&g++;break}}}a.a[b]=e.slice(g);return d} +CH.prototype.C=function(){if(0<this.g.length||0<this.f.length||0<this.i.length)return!0;if(!B(void 0))return!1;for(var a=GH(void 0,!1);5>=a;a++)if(this.a[a].length)return!0;return!1};function KH(){x.performance&&x.performance.now||E()}function HH(a){!a.b&&E()>a.v||a.l||(a.l=!0,ur(a.L,void 0,!0))}CH.prototype.c=function(){!this.b&&E()>this.v||this.m||(this.m=!0,this.b?this.O.call(x,this.B):ur(this.B,void 0,!0))}; +CH.prototype.M=function(a){if(this.b=a)this.m||this.c(),this.u||this.l||HH(this);this.v=this.b?0:E()+5E3};CH.prototype.j=function(){return sa};function LH(){CH.call(this);this.o=0;this.A=!1;var a=this;this.H=function(){a.xb()}}F(LH,CH);LH.prototype.j=function(){var a=this;a.o++;return function(){a.o--;0==a.o&&a.C()&&a.c()}};LH.prototype.zc=function(){MH(this)};LH.prototype.xb=function(){this.A=!1;MH(this);0<this.o||LH.R.xb.call(this)};LH.prototype.c=function(){this.A||(this.A=!0,ur(this.H,void 0,!0))};function MH(a){do var b=EH(a,!1);while(b)};function NH(a){this.f=null;this.b=0;this.c=!0;this.a=0;this.g=a;this.i=this.h=0}NH.prototype.setLineDash=function(a){this.f=a;this.c=!0;this.b=0;this.a=0<a.length?a[0]:0};NH.prototype.moveTo=function(a,b){this.h=a;this.i=b;this.g.moveTo(a,b)}; +NH.prototype.lineTo=function(a,b){var c=this.h,d=this.i,e=a-c,f=b-d,g=Math.sqrt(e*e+f*f);if(0!=g){e/=g;for(f/=g;0<g;){if(g>this.a){var h=this.a;g-=h;this.a=0}else h=g,this.a-=h,g=0;c+=e*h;d+=f*h;this.c?this.g.lineTo(c,d):this.g.moveTo(c,d);0==this.a&&(this.b=this.b==this.f.length-1?0:this.b+1,this.a=this.f[this.b],this.c=!this.c)}this.h=a;this.i=b}};function OH(a){return"rgba("+(a>>16&255)+","+(a>>8&255)+","+(a&255)+","+((a>>24&255)/255).toFixed(2)+")"}function PH(a){return"rgba("+Math.floor(255*a[0])+","+Math.floor(255*a[1])+","+Math.floor(255*a[2])+","+a[3]+")"};function QH(){} +QH.prototype.c=function(a,b,c,d,e){var f=c.g;var g=c.h[c.f];0>g||g>=f.c?f=0:(RH(f,g),f=f.b.length);g=f;if(!(1>g)){f=Array(g);for(var h=0;h<g;++h){var k=h;var l=h;var m=c.g,n=c.h[c.f];0>n||n>=m.c?l=new Float32Array(0):(RH(m,n),l=m.a.subarray(2*(0<l?m.b[l-1]:0),2*m.b[l]));f[k]=l}c=c.ka();if(h=SH(b,c))if(c=b=!1,g=null,h&&h.D&&(a.fillStyle=OH(aA(h,e)),b=!0),h&&0<h.c&&(k=uA(h,0,e),0<k&&(a.lineWidth=k*d,g=Zz(h,0,e),a.strokeStyle=OH(tA(h,0,e)),c=!0)),c||b){if(!(d=!c)&&(d=!g))b:{for(d=0;d<f.length;d++)if(!TH(f[d])){d= +!1;break b}d=!0}if(d)UH(a,f),b&&a.fill("evenodd"),c&&a.stroke();else{b&&(UH(a,f),a.fill("evenodd"));d=g;a.beginPath();e=a;d&&(e=a.setLineDash?a:new NH(a),e.setLineDash(d));e.lineJoin="round";for(b=0;b<f.length;b++){c=f[b];e.moveTo(c[0],c[1]);for(g=2;g<=c.length-2;g+=2)VH(c[g],c[g+1],c[g-2],c[g-1])?e.lineTo(c[g],c[g+1]):e.moveTo(c[g],c[g+1]);VH(c[0],c[1],c[c.length-2],c[c.length-1])&&e.lineTo(c[0],c[1])}a.stroke();d&&e.setLineDash([])}}}}; +function UH(a,b){a.beginPath();for(var c=0;c<b.length;c++){var d=b[c];a.moveTo(d[0],d[1]);for(var e=2;e<d.length;e+=2)a.lineTo(d[e],d[e+1]);a.lineTo(d[0],d[1])}}function TH(a){for(var b=0;b<a.length-2;b+=2)if(!VH(a[b],a[b+1],a[b+2],a[b+3]))return!1;return VH(a[0],a[1],a[a.length-2],a[a.length-1])}function VH(a,b,c,d){return(0<=a||0<=c)&&(256>=a||256>=c)&&(0<=b||0<=d)&&(256>=b||256>=d)};function WH(a,b){this.x=a;this.y=b}F(WH,eo);WH.prototype.add=function(a){this.x+=a.x;this.y+=a.y;return this};var XH=[.2,.2,.2,1],YH=[242/255,239/255,233/255,1],ZH=[0,0,0,1],$H=[0,0,0,0],aI=[1,1,1,0],bI=[1,1,1,.4],cI=[1,1,1,.2],dI=[0,0,0,0],eI=[.4,.4,.4,.4],fI=[.4,.4,.4,.2];function gI(a,b){return 0<=a.indexOf(1)?3:0<=a.indexOf(0)?0<=b.indexOf(1)?2:1:0}function hI(a,b){switch(gI(a,b)){case 1:return YH;case 2:return XH;case 3:return $H;default:return ZH}};function iI(){}function jI(a,b,c,d,e,f){c>e||d>f||(1>b[3]&&a.clearRect(c,d,e,f),0<b[3]&&(a.fillStyle=PH(b),a.fillRect(c,d,e,f)))}function kI(a,b,c,d,e,f,g){var h=(c.y-d.y)/(c.x-d.x);d=c.y-c.x*h;c=c.y-(c.x-e)*h;0>d&&0>c||d>f&&c>f||(a.beginPath(),a.moveTo(0,g),a.lineTo(0,d),a.lineTo(e,c),a.lineTo(e,g),a.closePath(),1>b[3]&&(a.globalCompositeOperation="destination-out",a.fillStyle="#000",a.fill(),a.globalCompositeOperation="source-over"),0<b[3]&&(a.fillStyle=PH(b),a.fill()))};var lI=Math.pow(2,22);function mI(){this.c=this.b=this.a=null}mI.prototype.w=function(){var a=[];if(null!==this.a){var b=this.a;a[0]=b}null!==this.b&&(b=this.b,a[1]=b);null!==this.c&&(b=this.c,a[2]=b);return a};mI.prototype.getExtension=function(){return null};function nI(a){return null==a.a?1:a.a} +yd(vy,96629873,11,function(){return new mI},function(){},function(a,b){for(;G(b);)switch(b.a){case 1:var c=J(b);a.a=c;break;case 2:c=K(b);a.b=c;break;case 3:c=K(b);a.c=c;break;default:H(b)}},function(a){if(null===a)a=null;else{var b=new mI;b.a=null;b.b=null;b.c=null;b.a=a.a;b.b=a.b;b.c=a.c;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a||a.b!==b.b||a.c!==b.c?!1:!0});function oI(a,b){return(a&65535|(b&65535)<<16)>>>0}function pI(a,b,c){a=Math.round(1073741824*(a*b+c));return a|0}function qI(a,b,c){a=Math.round(16*(a*b+c));return a&65535};function rI(a,b){return b?12>a:!1};function sI(a,b){this.A=a;this.v=b;this.l=this.j=0;this.u=1;this.s=16;this.h=new Uint32Array(3072);this.b=0;this.f=new Int32Array(1024);this.m=this.o=this.a=0;this.c=[];this.g=0;this.i=!1}sI.prototype.reset=function(a,b,c,d){this.j=B(a)?a:0;this.l=B(b)?b:0;this.u=B(c)?c:1;this.s=B(d)?d:16;this.a=this.b=0;this.i=!1;this.g=0};function tI(a){a.a=0;a.g=0}function uI(a){a.a=0;a.g=0} +function vI(a,b,c){var d=a.a/2,e=0==c?2:1;c=0==c?1:2;for(var f=0;f<d-2;f++)a.index(b),a.index((b+f+e)%d),a.index((b+f+c)%d)}function wI(a,b,c){var d=a.f;var e=a.a+1;e>=d.length&&(e=new Int32Array(2*e),e.set(d),d=e);a.f=d;a.f[a.a]=b;a.f[a.a+1]=c;a.a+=2}sI.prototype.index=function(a){this.i?(this.c[2*this.g]=this.f[2*a],this.c[2*this.g+1]=this.f[2*a+1],this.g=(this.g+1)%3,0==this.g&&xI(this)):yI(this,this.f[2*a],this.f[2*a+1])}; +function xI(a){function b(a,b,c,d){a=c-a;b=d-b;return a*a+b*b}var c=a.c[0],d=a.c[1],e=a.c[2],f=a.c[3],g=a.c[4],h=a.c[5],k=!1;if(262144<b(c,d,e,f)||262144<b(e,f,g,h)||262144<b(g,h,c,d))k=!0;if(k){k=(c+e+g)/3;var l=(d+f+h)/3;zI(a,k,l,c,d,e,f);zI(a,k,l,e,f,g,h);zI(a,k,l,g,h,c,d)}else yI(a,c,d),yI(a,e,f),yI(a,g,h)}function zI(a,b,c,d,e,f,g){f-=d;g-=e;var h=Math.ceil(Math.sqrt(f*f+g*g)/512);f/=h;g/=h;for(var k=0;k<h;k++)yI(a,b,c),yI(a,d+f*k,e+g*k),yI(a,d+f*(k+1),e+g*(k+1))} +function yI(a,b,c){var d=a.h;var e=a.b;e>=d.length&&(e=new Uint32Array(2*e),e.set(d),d=e);a.h=d;d=a.h;e=a.b;if(1==a.v){var f=a.u/a.s;d[e++]=pI(b,f,a.j);d[e++]=pI(c,f,a.l)}else d[e++]=oI(b,c);1==a.A&&(d[e++]=a.o,d[e++]=a.m);a.b=e};function AI(a){var b=a.getExtension(96629873);if(b&&(null==b.c?0:b.c))return lI;(b=null==a.u)||(b=null==Cy(a).a);if(b)return 16;a=Cy(a);switch(null==a.a?0:a.a){case 0:return 16;case 2:return 4;case 3:return 8;case 1:return 16;case 4:return 32;case 5:return 64;case 6:return 128;default:return 16}}function BI(a){for(var b=a.a,c=0;a.a<a.c;)ad(a),ad(a),c++;a.a=b;return c}function CI(a){for(var b=a.a,c=0;a.a<a.c;)ad(a),ad(a),ad(a),c++;a.a=b;return c} +function DI(a,b,c,d){for(var e=0,f=0,g=0;g<2*b;g+=2)e+=a.da(),f+=a.da(),d[g+0]=e/c,d[g+1]=f/c}function EI(a,b,c,d){for(var e=0,f=0,g=0,h=0;h<3*b;h+=3)e+=a.da()/c,f+=a.da()/c,g+=a.da()/c,d[h+0]=e,d[h+1]=f,d[h+2]=g} +function FI(a,b,c,d){var e=Sw(a);a=null===a.a?zd(a.g,a.j,a.K):Tc(null,null,a.a);if(12<=c)d=!1;else{var f=256*Math.pow(2,c-12)*b.C;16>=b.C&&(f=Math.max(f,256*b.C/8))}var g=c=0;b.V=b.a;b.h=0;b.g&&(b.v=[]);b.A=!1;b.B=!1;b.m=!1;b.c=!1;b.M=0;for(var h=b.u=0;!e.kb();h++){var k=e.da();var l=e.da();if(h==a.get())c+=k,g+=l,k=b,k.c=!1,k.h=0,k.u=0,a.next(),GI(b,c,g);else if(0<h&&d){var m=Math.sqrt(k*k+l*l);if(0<m){m=Math.ceil(m/f);for(var n=1;n<=m;n++)GI(b,c+n*k/m|0,g+n*l/m|0);c+=k;g+=l}}else c+=k,g+=l,GI(b, +c,g)}HI(b);Vc(e);Uc(a)}function II(a,b){var c=ex(a);var d=null===a.h?zd(a.a,a.o,a.O):Tc(null,null,a.h);a=null===a.g?zd(a.a,a.C,a.S):Tc(null,null,a.g);var e=0,f=0;JI(b);for(var g=0;!c.kb();g++){e+=c.da();f+=c.da();if(g==d.get()){var h=b;KI(h);JI(h);d.next()}GI(b,e,f);g==a.get()&&(b.c=!1,a.next())}KI(b);Vc(c);Uc(d);Uc(a)} +function LI(a,b,c){function d(a,c,d){var e=1;c&&(e+=c.length);for(var f=0,g=0,h=0,k=0;k<e;k++){var l=-1;c&&k<e-1&&(l=c[k]);if(a.kb())break;for(d?uI(b):b.a=0;!a.kb()&&f!=l;)g+=a.da(),h+=a.da(),wI(b,g,h),f++;if(d)vI(b,0,1);else{l=b;for(var u=l.a/2,w=0;w<u-2;w++){var y=w%2;l.index(w);l.index(w+1+y);l.index(w+2-y)}}}}if(fx(a)||null!=a.c||null!=a.l||null!=a.i||null!=a.m||null!=a.j){b.i=c;if(fx(a)||null!=a.c){(c=null!=a.c?!0:!1)?uI(b):tI(b);for(var e=0,f=0,g=ex(a);!g.kb();)e+=g.da(),f+=g.da(),wI(b,e,f); +Vc(g);if(fx(a)){for(e=ix(a);!e.kb();)b.index(e.next());Uc(e)}c&&vI(b,null==a.c?-1:a.c,0)}if(null!=a.l||null!=a.i)c=mx(a),e=null!=a.v||null!=a.D?nx(a):null,d(c,e,!0),Vc(c);if(null!=a.m||null!=a.j)c=ox(a),a=null!=a.B||null!=a.G?px(a):null,d(c,a,!1),Vc(c)}};function MI(a){this.h=a.a;this.j=a.b;this.g=null;this.b=(this.a=Ey(this.h)&&jy(Fy(this.h))?Fy(this.h).a:null)?this.a.length:0;this.i=-1;this.f=null;this.c=-1}function NI(a,b){if(a.i!=b){var c=a.a[b];if(null!=c.f||null!=c.c){var d=Sw(c);a.c=null!=c.i?null==c.i?0:c.i:BI(d);if(!a.f||a.f.length<2*a.c)a.f=new Float32Array(2*a.c);c=AI(a.h);DI(d,a.c,c,a.f);Vc(d)}a.g=a.j.a[1][b];a.i=b}}MI.prototype.ka=function(a){if(0>a||a>=this.b)return 0;NI(this,a);return this.g.ka()}; +function OI(a,b){Tw(a)&&0<b?(--b,Nw(a),a=a.a[b]):a=0;return a}function PI(a,b,c){Tw(b)&&c<Uw(b)?(Nw(b),a=b.a[c]):a=a.c;return a}function QI(a,b,c){if(0>b||b>=a.b)return 0;NI(a,b);a=Vw(a.a[b]);return 3==a?0==c?0:1:a}function RI(a,b,c){if(0>b||b>=a.b)return 0;NI(a,b);a=Ww(a.a[b]);return 3==a?0==c?0:1:a}function SI(a,b){if(0>b||b>=a.b)return 0;NI(a,b);return a.g.za};function TI(a){this.f=a.a;this.j=a.b;this.b=this.a=this.h=null;this.c=(this.g=Gy(this.f)&&ly(Hy(this.f))?Hy(this.f).a:null)?this.g.length:0;this.i=-1} +function RH(a,b){if(a.i!=b){var c=a.g[b];if(null==c.c?0:c.c){c=4;if(!a.a||a.a.length<2*c)a.a=new Float32Array(2*c);a.a[0]=0;a.a[1]=0;a.a[2]=256;a.a[3]=0;a.a[4]=256;a.a[5]=256;a.a[6]=0;a.a[7]=256;a.b=[c]}else{var d=ux(c),e=ex(d);c=null!=d.b?null==d.b?0:d.b:BI(e);if(!a.a||a.a.length<2*c)a.a=new Float32Array(2*c);var f=AI(a.f);DI(e,c,f,a.a);Vc(e);a.b=null!=d.h||null!=d.o?lx(d):[];a.b.push(c)}a.h=a.j.a[2][b];a.i=b}}TI.prototype.ka=function(a){if(0>a||a>=this.c)return 0;RH(this,a);return this.h.ka()}; +function UI(a,b){if(0>b||b>=a.c)return 0;RH(a,b);return a.h.za};function VI(a){this.g=a.a;this.j=a.b;this.l=a.j;this.h=null;this.i=null!=this.g.a&&ry(Ly(this.g))?Ly(this.g).Aa:[];this.f=0;this.i&&WI(this)}function XI(a){var b=a.f;return 0<=b&&b<a.i.length}r=VI.prototype;r.Sc=function(){return XI(this)};function WI(a){XI(a)&&(a.h=a.j.a[5][a.f])}r.hd=function(){this.f++;this.Sc()&&WI(this)};r.reset=function(){this.f=0;WI(this)};r.ka=function(){return this.h.ka()};r.jd=function(){return this.h.za};function YI(a,b){for(var c=Array(a.length),d=0;d<a.length;d++)c[d]={index:d,value:a[d]};c.sort(ZI);b?(a=b,a.length=c.length):a=Array(c.length);for(d=0;d<c.length;d++)a[d]=c[d].index;return a}function ZI(a,b){return a.value!=b.value?a.value-b.value:a.index-b.index};function $I(a,b){this.b=a;a=this.b;a=null==a.a?0:a.a.length;if(!b||b.length!=a){for(var c=Array(a),d=0;d<a;d++)c[d]=SI(this.b,d);b=YI(c,b)}this.c=b;this.a=0}function aJ(a){var b=new $I(a.b,a.c);b.a=a.a;return b}r=$I.prototype;r.Sc=function(){return this.c.length>this.a};r.hd=function(){this.a++};r.reset=function(){this.a=0};r.ka=function(){return this.b.ka(this.c[this.a])};r.jd=function(){return SI(this.b,this.c[this.a])};function bJ(a){this.g=a;a=this.g.c;for(var b=Array(a),c=0;c<a;c++)b[c]=UI(this.g,c);a=YI(b,void 0);this.h=a;this.f=0}r=bJ.prototype;r.Sc=function(){return this.h.length>this.f};r.hd=function(){this.f++};r.reset=function(){this.f=0};r.ka=function(){return this.g.ka(this.h[this.f])};r.jd=function(){return UI(this.g,this.h[this.f])};function cJ(a,b,c,d){this.type=a;this.c=B(b)?b:0;this.a=B(c)?c:null;this.b="boolean"==typeof d?d:!1}function dJ(a){a=eJ(a.l,a.g,a.f);a.Qb()&&a.Ib(3);return a.Ab()}function fJ(a){this.b=a;this.a=[];var b=a.data;this.a[0]=new $I(new MI(b));this.a[1]=new VI(b);this.a[2]=new bJ(new TI(b));a.b&&(a=a.b.data,this.a[3]=new $I(new MI(a)),this.a[4]=new VI(a),this.a[5]=new bJ(new TI(a)))}function gJ(a,b,c){return c?a.a[3+b]:a.a[b]}function hJ(a){for(var b=0;b<a.a.length;b++)a.a[b].reset()} +function iJ(a,b){this.b=a;this.a=b};function jJ(a,b,c,d){this.m=a;this.j=b;this.l=c;this.o=d;this.i=d.b;this.c=0;this.a=new fJ(d);this.f=this.g=null;this.h=0;this.b=[];a=this.a;b=this.b;c=[];for(d=0;d<a.a.length;d++)c[d]=a.a[d].Sc()?a.a[d].jd():-1;var e=-1,f=null;for(d=0;;d++){for(var g=-1,h=0;h<c.length;h++)0<=c[h]&&(0>g||c[h]<c[g])&&(g=h);if(0>g)break;h=a.a[g];var k=g%3,l=0,m=3<=g;if(0==k){l=m?a.b.b.a.f:a.b.a.f;var n=h.ka();l=SH(l,n).c;n=c[g];if(f){f.a<l&&(f.a=l);var p=h.b;var q=h.c[h.a];0>q||q>=p.b?p=0:(NI(p,q),p=p.g.b);p>e?(f=new iJ(d, +l),e=n):n<e&&(e=n)}else f=new iJ(d,l),f.a=l,e=n}else f&&(f=null);h.hd();c[g]=h.Sc()?h.jd():-1;b.push(new cJ(k,l,f,m))}hJ(a)}function kJ(a){a.h=0;a.c=0;hJ(a.a)} +function lJ(a,b,c,d,e){for(var f=a.b.length,g=0,h=a.h;h<f&&(0>e||g<e);h++){var k=a.b[h],l=gJ(a.a,k.type,k.b),m=k.type,n=(k.b?a.i:a.o).a.f;0==m?k.c>a.c&&(a.m.c(b,n,l,c,d,a.c),g++):(1==m?a.l.c(b,n,l,c,d):a.j.c(b,n,l,c,d),g++);if(k.a)if(h+1==f||a.b[h+1].a!=k.a)if(a.c<k.a.a-1){a.c++;h=k.a.b-1;a.g&&(a.a.a[0]=a.g,a.g=null);a.f&&(a.a.a[3]=a.f,a.f=null);continue}else a.g=null,a.f=null,a.c=0;else k.a.b==h&&a.c<k.a.a-1&&(a.g=aJ(gJ(a.a,0)),a.i&&(a.f=aJ(gJ(a.a,0,!0))));l.hd()}a.h=h};function mJ(){this.c={};this.b=this.a=null;this.f=0}mJ.prototype.has=function(a){a:{if(a=this.c[a]){if(a.b){a=!0;break a}nJ(this,a)}a=!1}return a};mJ.prototype.get=function(a){return this.c[a]};mJ.prototype.add=function(a){if(a&&!a.f){this.c[a.key]=a;a.f=!0;a.next=null;if(a.c=this.a)this.a.next=a;this.a=a;this.b||(this.b=this.a);for(this.f++;1E4<this.f;)this.b&&nJ(this,this.b)}};function nJ(a,b){delete a.c[b.key];b.f=!1;b.c?b.c.next=b.next:a.b=b.next;b.next?b.next.c=b.c:a.a=b.c;a.f--};function oJ(a,b,c,d){this.c=a;this.f=b;this.g=c;this.a=null;this.b=d} +function pJ(a,b,c){c=pF(2,c)/a.b;if(null!==a.a)a=a.a;else{var d=go("canvas"),e=d.getContext("2d"),f=pF(2,a.b);d.width=256*f;d.height=256*f;e.scale(f,f);e.fillStyle=a.c;e.fillRect(0,0,256,256);e.beginPath();e.strokeStyle=a.g;e.lineWidth=1;f=16;for(var g=256/f,h=1;h<g;h++){var k=h*f;e.moveTo(k,0);e.lineTo(k,256);k=h*f;e.moveTo(0,k);e.lineTo(256,k)}e.stroke();e.beginPath();e.lineWidth=2;e.strokeStyle=a.f;f=128;g=256/f;for(h=0;h<=g;h++)k=h*f,e.moveTo(k,0),e.lineTo(k,256),k=h*f,e.moveTo(0,k),e.lineTo(256, +k);e.stroke();a=a.a=d}b.drawImage(a,0,0,a.width*c,a.height*c)};function qJ(){}qJ.prototype.c=function(a,b,c){b=dJ(c);a.drawImage(b,0,0,256,256)};function rJ(){this.b=[];this.a=-1;this.c=0}var sJ=null;function tJ(){sJ||(sJ=new rJ);return sJ}function uJ(a,b,c){if(0==a.c){var d=go("canvas");d.width=b;d.height=c;return d}var e=a.a;for(d=0;d<a.a-1;d++)if(a.b[d]){var f=a.b[d].width>=b,g=a.b[d].height>=c;if(f||g)e=d;if(f&&g)break}d=a.b[e];a.b[e]=void 0;d.width<b||d.height<c?(d.width<b&&(d.width=b),d.height<c&&(d.height=c)):d.getContext("2d").clearRect(0,0,b,c);a.c--;if(0==a.c)a.a=-1;else if(e==a.a)for(;0<=a.a&&!a.b[a.a];)a.a--;return d} +function vJ(a,b){a.c==a.a+1?(a.b[a.c]=b,a.c++,a.a++):(a.b[a.b.indexOf(void 0)]=b,a.c++)};function wJ(){this.a=go("canvas");this.a.width=2048;this.a.height=2E3;this.f=this.c=0;this.b=40;this.g=0;this.h=[];xJ(this)}function xJ(a){for(;a.c!=a.f;)yJ(a);a.c=a.f=0;a.g=a.a.width*Math.floor(a.a.height/a.b)+1;a.h=Array(a.g);for(var b=Math.floor(a.a.height/a.b),c=0;c<b;c++)for(var d=Math.floor(a.a.width/a.b),e=0;e<d;e++){var f=e*a.b;zJ(a,new AJ(f,c*a.b,e==d-1?a.a.width-f:a.b,a.b))}} +function BJ(a,b,c){c>a.b&&(a.b=c,xJ(a));for(var d=0,e=0,f=a.a.width;d<b;){var g=yJ(a);d+=g.width;f=g.x<f?g.x:f;e=g.y;d<b&&g.x+g.width>=a.a.width&&(e=new AJ(f,e,d,a.b),zJ(a,e),d=0,f=a.a.width,e=0)}d-=b;c=new AJ(f,e,b,c);zJ(a,c);0!=d&&(e=new AJ(f+b,e,d,a.b),zJ(a,e));return c}function zJ(a,b){a.h[a.f]=b;a.f=++a.f%a.g}function yJ(a){var b=a.h[a.c];b&&(b.valid=!1);a.h[a.c]=null;a.c=++a.c%a.g;return b}function CJ(a,b){return b&&b.valid?a.a:null}var DJ=pb||!1; +function AJ(a,b,c,d){this.valid=!0;this.x=a;this.y=b;this.width=c;this.height=d};function EJ(a,b,c,d,e){this.canvas=a;this.width=b;this.height=c;this.a=0;this.c=d;this.b=e}function FJ(a){a.a--;0>=a.a&&(vJ(tJ(),a.canvas),a.b&&delete a.b.b[a.c])};function GJ(){this.a=[];this.b=0}GJ.prototype.reset=function(){this.b=0};GJ.prototype.append=function(a,b,c,d,e,f){var g=6*this.b;this.a[g+0]=a;this.a[g+1]=b;this.a[g+2]=c;this.a[g+3]=d;this.a[g+4]=e;this.a[g+5]=f;this.b++};function HJ(a){this.g=!!a;this.f=a?a:0;this.c=Array(this.f);this.a=0;this.b={}}HJ.prototype.has=function(a){return!!this.b[a]};HJ.prototype.get=function(a){return this.b[a]};HJ.prototype.set=function(a,b){this.g&&this.c[this.a]&&delete this.b[this.c[this.a]];this.b[a]=b;this.g&&(this.c[this.a]=a,this.a=(this.a+1)%this.f)};function IJ(){this.a=null;this.g=this.f=this.l=this.i=this.j=this.h=this.b=this.c=this.m=0}IJ.prototype.next=function(){if(0>this.b||this.b>=this.a.a)return!1;for(var a=this.i,b=this.l,c=JJ(this.a,this.b),d=KJ(this.a,this.b),e=c-a,f=d-b,g=this.m*(e*e+f*f),h=c-a,k=d-b,l=this.b+this.c;0<=l&&l<this.a.a;){var m=JJ(this.a,l),n=KJ(this.a,l),p=m-a,q=n-b,t=-p*k+q*h;if(t*t>g)break;c=m;d=n;e=p;f=q;l+=this.c}this.b=l;this.h=a;this.j=b;this.i=c;this.l=d;this.f=Math.atan2(f,e);this.g=Math.sqrt(e*e+f*f);return!0};function LJ(a,b){Pp.call(this);this.width=a;this.height=b}F(LJ,Pp);LJ.prototype.i=sa;function MJ(){return new Float32Array(16)}function NJ(a,b,c,d,e,f,g){a[0]=b;a[1]=0;a[2]=0;a[3]=0;a[4]=0;a[5]=c;a[6]=0;a[7]=0;a[8]=0;a[9]=0;a[10]=d;a[11]=0;a[12]=e;a[13]=f;a[14]=g;a[15]=1}function OJ(a,b){a[0]=b[0];a[1]=b[1];a[2]=b[2];a[3]=b[3];a[4]=b[4];a[5]=b[5];a[6]=b[6];a[7]=b[7];a[8]=b[8];a[9]=b[9];a[10]=b[10];a[11]=b[11];a[12]=b[12];a[13]=b[13];a[14]=b[14];a[15]=b[15]} +function PJ(a,b,c){var d=a[0],e=a[1],f=a[2],g=a[3],h=a[4],k=a[5],l=a[6],m=a[7],n=a[8],p=a[9],q=a[10],t=a[11],v=a[12],u=a[13],w=a[14];a=a[15];var y=b[0],A=b[1],z=b[2],C=b[3],I=b[4],S=b[5],ca=b[6],Z=b[7],ha=b[8],ea=b[9],ja=b[10],Y=b[11],ma=b[12],Ga=b[13],wa=b[14];b=b[15];c[0]=d*y+h*A+n*z+v*C;c[1]=e*y+k*A+p*z+u*C;c[2]=f*y+l*A+q*z+w*C;c[3]=g*y+m*A+t*z+a*C;c[4]=d*I+h*S+n*ca+v*Z;c[5]=e*I+k*S+p*ca+u*Z;c[6]=f*I+l*S+q*ca+w*Z;c[7]=g*I+m*S+t*ca+a*Z;c[8]=d*ha+h*ea+n*ja+v*Y;c[9]=e*ha+k*ea+p*ja+u*Y;c[10]=f*ha+ +l*ea+q*ja+w*Y;c[11]=g*ha+m*ea+t*ja+a*Y;c[12]=d*ma+h*Ga+n*wa+v*b;c[13]=e*ma+k*Ga+p*wa+u*b;c[14]=f*ma+l*Ga+q*wa+w*b;c[15]=g*ma+m*Ga+t*wa+a*b} +function QJ(a,b){var c=a[0],d=a[1],e=a[2],f=a[3],g=a[4],h=a[5],k=a[6],l=a[7],m=a[8],n=a[9],p=a[10],q=a[11],t=a[12],v=a[13],u=a[14];a=a[15];var w=c*h-d*g,y=c*k-e*g,A=c*l-f*g,z=d*k-e*h,C=d*l-f*h,I=e*l-f*k,S=m*v-n*t,ca=m*u-p*t,Z=m*a-q*t,ha=n*u-p*v,ea=n*a-q*v,ja=p*a-q*u,Y=w*ja-y*ea+A*ha+z*Z-C*ca+I*S;0!=Y&&(Y=1/Y,b[0]=(h*ja-k*ea+l*ha)*Y,b[1]=(-d*ja+e*ea-f*ha)*Y,b[2]=(v*I-u*C+a*z)*Y,b[3]=(-n*I+p*C-q*z)*Y,b[4]=(-g*ja+k*Z-l*ca)*Y,b[5]=(c*ja-e*Z+f*ca)*Y,b[6]=(-t*I+u*A-a*y)*Y,b[7]=(m*I-p*A+q*y)*Y,b[8]=(g*ea- +h*Z+l*S)*Y,b[9]=(-c*ea+d*Z-f*S)*Y,b[10]=(t*C-v*A+a*w)*Y,b[11]=(-m*C+n*A-q*w)*Y,b[12]=(-g*ha+h*ca-k*S)*Y,b[13]=(c*ha-d*ca+e*S)*Y,b[14]=(-t*z+v*y-u*w)*Y,b[15]=(m*z-n*y+p*w)*Y)}function RJ(a,b,c){var d=b[0],e=b[1],f=b[2];b=b[3];c[0]=d*a[0]+e*a[4]+f*a[8]+b*a[12];c[1]=d*a[1]+e*a[5]+f*a[9]+b*a[13];c[2]=d*a[2]+e*a[6]+f*a[10]+b*a[14];c[3]=d*a[3]+e*a[7]+f*a[11]+b*a[15]} +function SJ(a,b,c,d){var e=Math.cos(b);b=Math.sin(b);var f=Math.cos(c);c=Math.sin(c);var g=Math.cos(d);d=Math.sin(d);a[0]=e*g-f*b*d;a[1]=f*e*d+g*b;a[2]=d*c;a[3]=0;a[4]=-e*d-g*f*b;a[5]=e*f*g-b*d;a[6]=g*c;a[7]=0;a[8]=c*b;a[9]=-e*c;a[10]=f;a[11]=0;a[12]=0;a[13]=0;a[14]=0;a[15]=1};function TJ(a,b){this.a=a;this.b=b;this.altitude=0;this.screenX=a;this.screenY=b;this.c=!1}var UJ=new Float32Array(2),VJ=new Float32Array(2),WJ=new Float32Array(4);function XJ(){this.a=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];this.c=!1;this.b=this.data=null}function YJ(a){a.data=null;a.b=null}function ZJ(a,b){var c=a.a[12],d=0,e=0,f=0,g=0;b=b.a;for(var h=0;4>h;h++){var k=b[2*h]+c*b[2*h+1],l=b[2*h+1]-c*b[2*h];0==h?(d=e=k,f=g=l):(k<d&&(d=k),k>e&&(e=k),l<f&&(f=l),l>g&&(g=l))}c=a.a[15];b=a.a[16];h=a.a[14];return a.a[13]<=e&&d<=c&&h<=g&&f<=b};function $J(a,b){this.f=a;this.a=[];this.b=0;this.c=b}$J.prototype.get=function(){this.b==this.a.length&&this.a.push(new this.f);return this.a[this.b++]};function aK(a){if(a.c)for(var b=0;b<a.b;b++)a.c(a.a[b]);a.b=0};function bK(){this.a=new $J(XJ,YJ)} +function cK(a,b,c,d,e,f,g,h){a=a.a.get();a.data=g||null;a.b=h||null;g=d-b;h=e-c;var k=Math.sqrt(g*g+h*h);if(0<k){var l=f*-h/(2*k);f=f*g/(2*k)}else l=f/2,f/=2;a.a[0]=b+l;a.a[1]=c+f;a.a[2]=b-l;a.a[3]=c-f;a.a[4]=d+l;a.a[5]=e+f;a.a[6]=d-l;a.a[7]=e-f;l=0<l?l:-l;f=0<f?f:-f;b<d?(a.a[8]=b-l,a.a[10]=d+l):(a.a[8]=d-l,a.a[10]=b+l);c<e?(a.a[9]=c-f,a.a[11]=e+f):(a.a[9]=e-f,a.a[11]=c+f);0!=g&&0!=h?(a.c=!0,g=h/g,a.a[12]=g,c=b=a.a[0]+g*a.a[1],e=d=a.a[1]-g*a.a[0],f=a.a[6]+g*a.a[7],g=a.a[7]-g*a.a[6],f<b&&(b=f),f>c&& +(c=f),g<d&&(d=g),g>e&&(e=g),a.a[13]=b,a.a[15]=c,a.a[14]=d,a.a[16]=e):a.c=!1;return a}bK.prototype.reset=function(){aK(this.a)};function dK(){this.c=[];this.H=this.wb=this.J=this.g=0;this.l=this.G=null;this.v=0;this.B=this.ab=!1;this.f=this.j=0;this.s=!1;this.a=this.b=null;this.u=!1;this.h=-1;this.C=!0;this.m=this.D=0;this.K=22;this.i=this.I=this.A=!1;this.o=new oq(0,0,0,0);this.uc=!1}function eK(a,b){b.label=a;a.c.push(b)}function fK(a,b){return a.g-b.g||a.h-b.h}dK.prototype.Gb=function(a,b,c,d){this.ab!=a&&(c||!this.C?this.j=b-d:(c=this.j+d-b,this.j=0<c?b-c:b),this.ab=a,a=this.j+d,this.D<a&&(this.D=a));return this.D-b}; +function gK(a,b,c){var d=!1;a.ab&&1>a.f?(a.f=0<c?(b-a.j)/c:1,1<a.f&&(a.f=1),d=!0):!a.ab&&0<a.f&&(a.f=0<c?1-(b-a.j)/c:0,0>a.f&&(a.f=0),d=!0);a.A!=a.I&&(a.I=a.A,d=!0);return d}var hK=new oq(0,0,0,0);function iK(a){var b=a.c;0<b.length&&b[0].l(a.o);for(var c=1;c<b.length;++c){b[c].l(hK);var d=a.o,e=hK;d.left=Math.min(d.left,e.left);d.top=Math.min(d.top,e.top);d.right=Math.max(d.right,e.right);d.bottom=Math.max(d.bottom,e.bottom)}} +function jK(a){var b=kK;a=a.c;for(var c=[],d=0;d<a.length;++d)c=c.concat(a[d].s(b));return c}function lK(a){return!(a.H&8)&&a.A}function mK(a){this.type=a;this.label=null;this.o=this.f=this.a=0;this.c=null}function nK(a,b){return a.label.g-b.label.g||a.o-b.o}mK.prototype.A=sa;function oK(a){var b=new mJ;this.g=a;this.c=DJ;this.f=null;this.b=Array(2);this.h=new HJ(this.c?1E3:void 0);this.i=b;this.a=new GJ}var pK=new IJ;function qK(a,b,c,d,e,f,g){if(0!=c.f){for(var h=0;h<c.c.length;++h){var k=c.c[h].type;1!=k&&0!=k||rK(a,b,c.c[h],d,e,f,g)}for(h=0;h<c.c.length;++h)k=c.c[h].type,1!=k&&0!=k&&rK(a,b,c.c[h],d,e,f,g)}} +function rK(a,b,c,d,e,f,g){var h=0==c.type||5==c.type||2==c.type;h&&(b.save(),b.translate(-f,-g));switch(c.type){case 1:f=-1*c.height/2;g=c.width;var k=c.height,l=c.m,m=c.g;d=d.data;e=SH(e,c.a);if(c.label.b){d=sK(a.g,tK(d),uK(d),d.getZoom(),c.label.b,a.b);for(var n=0;n<d;++n){var p=vK(e);wK(b,a.b[2*n]+c.oa,a.b[2*n+1]+c.b+f,g,k,l,p.fill,p.outline,m,a.b[2*n],a.b[2*n+1],c.i,c.label.f)}}break;case 0:a=SH(e,c.a);e=c.label.f;d=c.f;xK(c.label.a,d);yK(b,c,d,e,a);break;case 3:f=c.c;zK(a,f,d.a.Y,e,c,d.data.getZoom()); +if(c.label.b)for(e=sK(a.g,tK(d.data),uK(d.data),d.data.getZoom(),c.label.b,a.b),d=0;d<e;++d)g=a.b[2*d]+c.oa,k=a.b[2*d+1]+c.b,g-=f.h,(l=AK(f))&&BK(b,l,f,g,k,c.label.f);break;case 4:d=d.data;f=d.getZoom();g=nI(wy(d.a));if((k=CK(e,c.a))&&fA(k,f)&&(k=fA(k,f),(g=Zs(k,c.g.width,c.g.height,k.b||g,c.text))&&0!=g.width&&0!=g.height&&(e=SH(e,c.a))&&fA(e,f)&&(e=c.label.f,0!=e&&c.label.b)))for(d=sK(a.g,tK(d),uK(d),d.getZoom(),c.label.b,a.b),f=0;f<d;++f)DK(b,g,a.b[2*f],a.b[2*f+1],c.g,c.h,e);break;case 5:a=d.data; +d=a.getZoom();a=nI(wy(a.a));(f=CK(e,c.a))&&fA(f,d)&&(f=fA(f,d),(a=Zs(f,c.g.width,c.g.height,f.b||a))&&0!=a.width&&0!=a.height&&(e=SH(e,c.a))&&fA(e,d)&&(e=c.label.f,0!=e&&(g=c.label.a,xK(g,c.f),k=EK(g.c,FK(c)),d=JJ(g,k),f=KJ(g,k),g=Math.atan2(KJ(g,Math.ceil(k))-KJ(g,Math.floor(k)),JJ(g,Math.ceil(k))-JJ(g,Math.floor(k))),b.save(),b.translate(d,f),b.rotate(g+(lK(c.label)?Math.PI:0)),DK(b,a,0,0,c.g,c.j,e),b.restore())));break;case 2:if(f=c.c,zK(a,f,d.a.V,e,c,d.data.getZoom()),k=(g=f.a)&&g.b,f.canvas|| +f.b||f.c||k)n=k?null:AK(f),k=c.label.f,l=c.f,lK(c.label)&&c.g&&(l*=-1),g?(m=GK(e,c.a),e=SH(e,c.a),f=HK(g,n,f.b),IK(a,b,m,e,d.data.getZoom(),c,f,lK(c.label),l,k)):JK(b,c,n,lK(c.label),l,k)}h&&b.restore()} +function zK(a,b,c,d,e,f){var g=!!b.canvas||!!b.c||KK(a,b.b);b=b.a;if(!(b&&b.b||g)&&(c=c.j,b=GK(d,e.a),d=SH(d,e.a),e.c))if(e=e.c,e.a)LK(c,e,b,d,f,a.i);else if(e.g)a:{var h=a=null;if((g=e.g)&&g.c&&g.c.complete){if(b=MK(c,g.key,b))if(g.b){h=g.c;var k=g.b;if(d.s){var l=NK(c,k.width,k.height),m=l.getContext("2d");m.globalAlpha=(eA(d,f)>>24&255)/255;m.drawImage(h,k.left,k.top,k.width,k.height,0,0,k.width,k.height);m.globalAlpha=1;h=l}else h=null}else{if(g.a&&g.c){e.c=new OK(g.a,g.c,(dA(d,f)>>24&255)/255); +break a}}else a=PK(c,g.c,f,d,g.a.left,g.a.top,g.a.width,g.a.height),g.b&&(h=PK(c,g.c,f,d,g.b.left,g.b.top,g.b.width,g.b.height,g.b.width));k=g.a;h&&(k=(g.b.width-g.a.width)/2,l=(g.b.height-g.a.height)/2,k=Math.floor(k),l=1==g.b.height%2?Math.floor(l):Math.floor(l+.5),e.h=k,e.j=l,m=h.getContext("2d"),m.globalCompositeOperation="source-over",b?(d.l&&(m.globalAlpha=(dA(d,f)>>24&255)/255),m.drawImage(g.c,g.a.left,g.a.top,g.a.width,g.a.height,k,l,g.a.width,g.a.height),m.globalAlpha=1):m.drawImage(a,0, +0,g.a.width,g.a.height,k,l,g.a.width,g.a.height),a=h,k=g.b);a&&(c.a?e.b=QK(a,k):e.canvas=a)}}else e.f&&(a=e.f)&&(g=a.text,b=a.a,h=a.b,k=b+10,l=NK(c,a.width+10,k),m=l.getContext("2d"),RK(m,g,k/2,b,h,c.c,d,f),c.a?e.b=QK(l,new pq(0,0,a.width+10,a.a+10)):e.canvas=l)} +function JK(a,b,c,d,e,f){var g=b.label.a;xK(g,e);e=b.c;var h=SK(g.c,g.f);b=b.b;d?1==g.h?(d=h-b,b=h-b-e.width):(d=h+e.width+b,b=h+b):(d=h+b,b=h+b+e.width);h=EK(g.c,d);b=EK(g.c,b);d=JJ(g,h);h=KJ(g,h);g=Math.atan2(KJ(g,b)-h,JJ(g,b)-d);a.save();a.translate(d,h);a.rotate(g);0!=g?(g=!!(a.imageSmoothingEnabled||a.mozImageSmoothingEnabled||a.webkitImageSmoothingEnabled||a.msImageSmoothingEnabled),oF(a,!0),BK(a,c,e,0,0,f),oF(a,g)):BK(a,c,e,0,0,f);a.restore()} +function IK(a,b,c,d,e,f,g,h,k,l){a.c&&!a.f&&(a.f=new wJ);var m=f.c,n=m.a.j;a.a.reset();TK(f,h,k,a.a);1>l&&(b.globalAlpha=l);for(f=0;f<a.a.b;f++)h=UK(a,c,d,e,m,g,a.a.a[6*f+4],a.a.a[6*f+5]),0<h.width&&0<h.height&&(b.save(),b.translate(a.a.a[6*f+0],a.a.a[6*f+1]),b.rotate(a.a.a[6*f+2]),k=a.a.a[6*f+3],a.c?b.drawImage(CJ(a.f,h),h.x,h.y,h.width,h.height,k,-(h.height/n/2),h.width/n,h.height/n):b.drawImage(h.canvas,0,0,h.width,h.height,k,-(h.height/n/2),h.width/n,h.height/n),b.restore());1>l&&(b.globalAlpha= +1)} +function UK(a,b,c,d,e,f,g,h){var k=e.a;b=VK(k,b);e=b.b;var l=k.c.length/4,m=k.g?Math.floor(l/2):0;if(l=h==l&&g==m)var n=b.a;else{var p=g+"-"+h;n=e[p]}if(!KK(a,n)){n=h-1;var q=[],t=c.s?eA(c,d):0;q.push(c.l?dA(c,d):0);q.push(t);c=k.c[4*g];for(d=g;d<h;d++)q.push(k.i[d]),q.push(k.c[4*d]-c);h=q.join("");c=a.h;if(!c.has(h)||!KK(a,c.get(h))){k=k.c;t=b.c;var v=b.f;q=d=k[4*g];for(var u=n;u>=g;u--){var w=k[4*u]+k[4*u+2];w>q&&(q=w)}u=Math.ceil(q-d);q=WK(f);if(a.c){var y=BJ(a.f,u,q);w=CJ(a.f,y)}else{w=uJ(tJ(),u, +q);var A=new EJ(w,u,q,h,a.h)}w=w.getContext("2d");a.c&&(w.save(),w.translate(y.x,y.y),w.clearRect(0,0,u,q));if(0<m)for(w.globalAlpha=v/255,u=g;u<=n;u++){v=u-m;var z=k[4*v+2],C=k[4*v+3];if(0!=z&&0!=C){v=(q-C)/2;var I=u-m;w.drawImage(f.a?f.a[I].b:f.f,XK(f,I),f.a?f.a[I].a.top:f.b?f.b.y:0,z,C,k[4*u]-d-(z-k[4*u+2])/2,v,z,C)}}for(w.globalAlpha=t/255;g<=n;g++)m=k[4*g+2],t=k[4*g+3],0!=m&&0!=t&&(v=(q-t)/2,w.drawImage(f.a?f.a[g].b:f.f,XK(f,g),f.a?f.a[g].a.top:f.b?f.b.y:0,m,t,k[4*g]-d,v,m,t));a.c&&w.restore(); +n=a.c?y:A;c.set(h,n)}n=c.get(h);a.c||n.a++;l?b.a=n:e[p]=n}return n} +function TK(a,b,c,d){var e=a.label.a;xK(e,c);var f=a.c;c=f.a.c;var g=f.a.j,h=f.a.g,k=SK(e.c,e.f);a=a.b;a=EK(e.c,b?1==e.h?k-a:k+f.width+a:k+a);if(!(0>a||a>e.a-1))for(pK.a=e,pK.m=5,b=B(b)&&b,pK.c=b?-1:1,e=0|a,pK.b=b&&e!=a?e:e+pK.c,pK.h=0,pK.j=0,pK.i=JJ(pK.a,a),pK.l=KJ(pK.a,a),pK.f=0,pK.g=0,b=c.length/4,h=h?Math.floor(b/2):0,e=0;h<b&&pK.next();){a=e+pK.g;f=a*g;for(var l=k=h;l<b&&!(c[4*l]+c[4*l+2]/2>f);l++)h++;d.append(pK.h,pK.j,pK.f,c[4*k]/g-e,k,h);e=a}}function KK(a,b){return a.c?!!b&&b.valid:!!b} +function AK(a){return a.b&&a.b.valid?YK?CJ(YK,a.b):null:a.c?a.c.a:a.canvas?a.canvas:null} +function yK(a,b,c,d,e){var f=vK(e);if("magenta"!=f.fill){var g=b.label.a,h=SK(g.c,g.f)+b.b,k=EK(g.c,h);g=EK(g.c,h+b.width);1>d&&(a.globalAlpha=d);a.save();h=0;e.j&&(h=Tz(e.b,8));e=b.height+3;if(0<h){var l=b.label.a,m=e/2,n=0<=c?1:-1;c=n*m;m=-n*(m-h);n=0;for(var p=Math.floor(k);p<=Math.ceil(g);++p){var q=Yn(p,k,g);var t=JJ(l,q);q=KJ(l,q);if(t!=z||q!=C){if(0<n){var v=t-z;var u=q-C;var w=1/Math.sqrt(v*v+u*u);v*=w;u*=w;if(1<n){var y=t-y;var A=q-A;w=1/Math.sqrt(y*y+A*A);y*=w;A*=w;a.lineTo(z+-A*c,C+y*c)}else A= +2*v,y=2*u,a.beginPath(),a.moveTo(z-A+-u*m,C-y+v*m),a.lineTo(z-A+-u*c,C-y+v*c)}y=z;A=C;var z=t;var C=q;++n}}0<n&&(A=2*v,y=2*u,a.lineTo(t+A+-u*c,q+y+v*c),a.lineTo(t+A+-u*m,q+y+v*m));a.strokeStyle=f.outline;a.lineWidth=2*h;a.lineCap="butt";a.stroke()}b=b.label.a;z=JJ(b,k);C=KJ(b,k);v=Math.ceil(k);v==k&&(v+=1);t=z-JJ(b,v);v=C-KJ(b,v);u=Math.sqrt(t*t+v*v);a.beginPath();a.moveTo(z+2*t/u,C+2*v/u);for(k=Math.ceil(k);k<g;++k)z=JJ(b,k),C=KJ(b,k),a.lineTo(z,C);z=JJ(b,g);C=KJ(b,g);k=Math.floor(g);k==g&&--k;t= +z-JJ(b,k);v=C-KJ(b,k);u=Math.sqrt(t*t+v*v);a.lineTo(z+2*t/u,C+2*v/u);a.strokeStyle=f.fill;a.lineWidth=e;a.stroke();a.restore();1>d&&(a.globalAlpha=1)}} +function wK(a,b,c,d,e,f,g,h,k,l,m,n,p){var q=b+f/2,t=c+f/2,v=d-f,u=e-f;1>p&&(a.globalAlpha=p);a.lineWidth=f;a.strokeStyle=h;a.fillStyle=g;0<n&&(a.shadowOffsetX=n,a.shadowOffsetY=n,a.shadowBlur=2,a.shadowColor="rgba(0, 0, 0, 0.2)");"magenta"!=g&&(0<k?(ZK(a,b,c,b+d,c+e,l,m,k,0),a.fill()):a.fillRect(b,c,d,e));0<n&&(a.shadowOffsetX=0,a.shadowOffsetY=0,a.shadowBlur=0);"magenta"!=h&&0<f&&(k?(ZK(a,b,c,b+d,c+e,l,m,k,f/2),a.stroke()):a.strokeRect(q,t,v,u));1>p&&(a.globalAlpha=1)} +function ZK(a,b,c,d,e,f,g,h,k){b+=k;c+=k;d-=k;e-=k;h-=k;a.beginPath();a.moveTo(b,c);g<c&&(a.lineTo(f-h,c),a.lineTo(f,c-h),a.lineTo(f+h,c));a.lineTo(d,c);f>d&&(a.lineTo(d,g-h),a.lineTo(d+h,g),a.lineTo(d,g+h));a.lineTo(d,e);g>e&&(a.lineTo(f+h,e),a.lineTo(f,e+h),a.lineTo(f-h,e));a.lineTo(b,e);f<b&&(a.lineTo(b,g+h),a.lineTo(b-h,g),a.lineTo(b,g-h));a.lineTo(b,c)} +function BK(a,b,c,d,e,f){f*=c.c?c.c.b:1;1>f&&(a.globalAlpha=f);var g=c.f,h=c.g,k=c.b||c.c;c=h?h.la:1;var l=k?k.x:0,m=k?k.y:0;if(k){var n=k.width;g=k.height}else g?(n=g.width+10,g=g.a+10):h&&h.b?(n=h.b.width,g=h.b.height):h&&h.a?(n=h.a.width,g=h.a.height):(n=b.width,g=b.height);a.drawImage(b,l,m,n,g,Math.floor(d+.5),Math.floor(e+.5-g/c/2),n/c,g/c);1>f&&(a.globalAlpha=1)} +function DK(a,b,c,d,e,f,g){1>g&&(a.globalAlpha=g);a.drawImage(b,e.left,e.top,e.width,e.height,Math.floor(c+.5+f.left),Math.floor(d+.5+f.top),f.width,f.height);1>g&&(a.globalAlpha=1)}function vK(a){var b="magenta",c="magenta";a.j&&(b=OH(Uz(a,0)),c=OH(Uz(a,4)));return{fill:b,outline:c}};function $K(a){this.a=a}function aL(a,b,c,d,e,f){d=pF(2,d);b.save();b.scale(d,d);d=[];for(var g=0;g<c.length;++g)for(var h=c[g];h;){for(var k=h.a.j,l=0;l<k.length;++l)d.push({label:k[l],Md:h});h=h.b}d.sort(function(a,b){return a.label.g-b.label.g||a.label.h-b.label.h});for(l=0;l<d.length;++l)c=d[l].label,h=d[l].Md,qK(a.a,b,c,h,h.a.f,e,f);b.restore()};function bL(){this.b=0;this.a=new Float32Array(0)}function cL(a,b,c){a.a.length<b&&(a.a=new Float32Array(b));a.b=b;a=a.a;for(var d=c[0],e=c[1],f=a[0]=0,g=1;g<b;g++){var h=2*g,k=c[h];h=c[h+1];d-=k;e-=h;f+=Math.sqrt(d*d+e*e);a[g]=f;d=k;e=h}}function SK(a,b){var c=Math.min(Math.max(Math.floor(b),0),a.b-2);b-=c;return(1-b)*a.a[c]+b*a.a[c+1]} +function EK(a,b){if(0==b)return 0;for(var c=0,d=a.b-1;1<d-c;){var e=Math.floor((c+d)/2);b>a.a[e]?c=e:d=e}e=a.a[c];d=a.a[d];return e==d?0<Math.sign(b)?a.b:-1:c+(b-e)/(d-e)};function dL(a){this.l=a;this.a=this.l.length/2;var b=this.l,c=b.length/2,d=new Float32Array(c);if(!(2>c))for(var e=1;e<c-1;++e){var f=e-1,g=e,h=e+1;var k=b[2*g+0],l=b[2*g+1];g=k-b[2*f+0];f=l-b[2*f+1];k=b[2*h+0]-k;h=b[2*h+1]-l;l=(g*g+f*f)*(k*k+h*h);if(0==l)g=0;else{l=Math.sqrt(l);var m=k*f-h*g;g=0==m?0:(l-(g*k+f*h))/m}d[e]=g}this.i=d;this.g=new Float32Array(a.length);for(b=0;b<a.length;++b)this.g[b]=a[b];this.b=new bL;cL(this.b,this.a,this.l);a=this.b;b=new bL;b.b=a.b;b.a=new Float32Array(a.a.length); +for(c=0;c<a.b;++c)b.a[c]=a.a[c];this.c=b;this.m=this.altitude=0;this.j=null;this.o=!1;this.f=0;this.h=1}function eL(a,b){b=Math.ceil(b);for(var c=0,d=Math.floor(0)+1;d<b;++d)c+=a.i[d];return 2*c}function xK(a,b){if(a.m!=b){a.j||(a.j={},a.j[0]=a.g);if(a.j[b])a.j[a.m]=a.g,a.g=a.j[b];else{var c=new Float32Array(a.j[0].subarray(0));fL(c,a.a,b);a.j[b]=c;a.g=c}cL(a.c,a.a,a.g);a.m=b}} +function fL(a,b,c){for(var d=a[0],e=a[1],f=0;f<b;++f){var g=Math.min(b-1,f+1),h=a[2*f],k=a[2*f+1],l=a,m=f,n=h,p=k,q=a[2*g];g=a[2*g+1];var t=c;q-=n;g-=p;n-=d;p-=e;d=Math.sqrt(q*q+g*g);e=Math.sqrt(n*n+p*p);0==d?(l[2*m]+=-p/e*t,l[2*m+1]+=n/e*t):0==e?(l[2*m]+=-g/d*t,l[2*m+1]+=q/d*t):(n=(n/e+q/d)/2,p=(p/e+g/d)/2,e=n*n+p*p,.25>e&&(e=.25),l[2*m]-=p/e*t,l[2*m+1]+=n/e*t);d=h;e=k}}function JJ(a,b){var c=Math.min(Math.max(Math.floor(b),0),a.a-2);b-=c;return(1-b)*a.g[2*c]+b*a.g[2*(c+1)]} +function KJ(a,b){var c=Math.min(Math.max(Math.floor(b),0),a.a-2);b-=c;return(1-b)*a.g[2*c+1]+b*a.g[2*(c+1)+1]}function gL(a,b){var c=Math.min(Math.max(Math.floor(b),0),a.a-2);b-=c;return(1-b)*a.l[2*c]+b*a.l[2*(c+1)]}function hL(a,b){var c=Math.min(Math.max(Math.floor(b),0),a.a-2);b-=c;return(1-b)*a.l[2*c+1]+b*a.l[2*(c+1)+1]};function iL(a){this.b=pF(2,a);this.f=go("canvas");this.f.width=this.f.height=256*this.b;this.a=this.f.getContext("2d");this.a.scale(this.b,this.b);this.a.lineJoin="round";this.ff=new Float32Array(128)} +iL.prototype.c=function(a,b,c,d,e,f){var g=c.ka();if(g=SH(b,g)){var h=g.c;if(!(f>=h)){var k=tA(g,f,e)>>24&255;if(0!=k){b=null;var l=Zz(g,f,e);l&&(b=l.map(function(a){return a*d}));l=Yz(g,f,e)*d;var m;if(b)var n=m=0;else n=QI(c.b,c.c[c.a],f),m=RI(c.b,c.c[c.a],f);a.lineCap=0!=n||0!=m?"round":"butt";a.lineJoin="round";n=uA(g,f,e)*d;m=OH(tA(g,f,e));0==f&&1<h&&255>(tA(g,1,e)>>24&255)?jL(this,a,c,l,g,d,e):(255>k&&(e=a.globalCompositeOperation,a.globalCompositeOperation="destination-out",kL(this,a,c,l,n, +"rgba(0,0,0,1.00)",b),a.globalCompositeOperation=e),kL(this,a,c,l,n,m,b))}}}}; +function jL(a,b,c,d,e,f,g){a.a.clearRect(0,0,256,256);var h=QI(c.b,c.c[c.a],0);var k=RI(c.b,c.c[c.a],0);var l=QI(c.b,c.c[c.a],1);var m=RI(c.b,c.c[c.a],1);a.a.globalCompositeOperation="source-over";a.a.lineCap=0!=h||0!=k?"round":"butt";kL(a,a.a,c,d,uA(e,0,g)*f,OH(tA(e,0,g)),Zz(e,0,g));a.a.globalCompositeOperation="destination-out";a.a.lineCap=0!=l||0!=m?"round":"butt";kL(a,a.a,c,d,uA(e,1,g)*f,"black",null);b.drawImage(a.f,0,0,Math.floor(256*a.b),Math.floor(256*a.b),0,0,256,256)} +function kL(a,b,c,d,e,f,g){if(0!=e){var h=b;g&&(h=b.setLineDash?b:new NH(b),h.setLineDash(g));b.lineWidth=e;b.strokeStyle=f;b.beginPath();e=c.b;f=c.c[c.a];0>f||f>=e.b?e=0:(e=e.a[f],e=Tw(e)?Uw(e)+1:1);for(f=0;f<e;f++){var k=c.b;var l=c.c[c.a],m=f;if(0>l||l>=k.b)k=0;else{NI(k,l);l=k.a[l];var n=OI(l,m);k=PI(k,l,m)-n}m=a;n=c.b;var p=c.c[c.a],q=f;l=a.ff;if(0>p||p>=n.b)l=l||new Float32Array(0);else{NI(n,p);var t=n.a[p];p=OI(t,q);q=PI(n,t,q);n=n.f.subarray(2*p,2*q);l?(l.length<n.length&&(l=new Float32Array(n.length)), +l.set(n)):l=n}m=m.ff=l;0!=d&&fL(m,k,-d);h.moveTo(m[0],m[1]);for(l=2;l<2*k-1;l+=2)h.lineTo(m[l],m[l+1])}b.stroke();g&&h.setLineDash([])}};function lL(a){this.f=a;this.a=this.g=this.b=null;this.c=0}function XK(a,b){return a.a?a.a[b].a.left:(a.b?a.b.x:0)+a.g[b]}function WK(a){if(!a.c)if(a.b)a.c=a.b.height;else if(a.a)for(var b=0;b<a.a.length;b++)a.a[b].a.height>a.c&&(a.c=a.a[b].a.height);else a.c=a.f.height;return a.c};function mL(a,b,c,d,e,f,g,h,k){this.key=a;this.height=b;this.i=c;this.b=null;this.h=d;this.a=e;this.l=f;this.c=g;this.j=h;this.g=k;this.f={}}function nL(){this.a=null;this.b={};this.f=this.c=255}function HK(a,b,c){b=new lL(b);a.b?b.a=a.b:(b.b=c,b.g=a.l);return b}function VK(a,b){a.f[b]||(a.f[b]=new nL);return a.f[b]};function oL(a,b){LJ.call(this,a,b);this.a=this.g=this.f=this.c=this.b=this.canvas=null;this.j=this.h=0;this.l=DJ}F(oL,LJ);oL.prototype.i=function(){this.c=this.b=this.canvas=null;this.a&&(this.a.b=null)};oL.prototype.X=function(){if(!this.l){var a=tJ();this.canvas&&vJ(a,this.canvas);if(this.a)for(var b in this.a.f){a=this.a.f[b];if(a.a){var c=a.a;FJ(c)}for(var d in a.b)c=a.b[d],FJ(c)}}oL.R.X.call(this)}; +function OK(a,b,c){this.x=a.left;this.y=a.top;this.width=a.width;this.height=a.height;this.a=b;this.b=c};function pL(a){this.key=a;this.a=this.b=null;this.f=!1;this.c=this.next=null};function qL(a,b,c){var d="";b&2&&(d+="italic ");var e="";b&16&&(e="300 ");b&8&&(e="500 ");b&1&&(e="700 ");return d=d+e+(a+"px ")+c};function RK(a,b,c,d,e,f,g,h){d=qL(d,e,f);a.font!=d&&(a.font=d);a.textBaseline="middle";d=e="magenta";g.l&&(e=OH(dA(g,h)));g.s&&(d=OH(eA(g,h)));g=e;h=d;"magenta"!=h&&(a.strokeStyle=h,a.lineWidth=2,a.strokeText(b,0,c));"magenta"!=g&&(a.fillStyle=g,a.lineWidth=2,a.fillText(b,0,c))};function rL(a){this.c=a;this.a=DJ;this.b={}}var sL=null,tL=null,uL=null,YK=null;function QK(a,b){YK||(YK=new wJ);var c=YK;b=BJ(c,b.width,b.height);c=CJ(c,b).getContext("2d");c.clearRect(b.x,b.y,b.width,b.height);c.drawImage(a,0,0,b.width,b.height,b.x,b.y,b.width,b.height);return b}function MK(a,b,c){var d=a.b[b];if(void 0==d)a.b[b]=c;else if(d!=c)return!1;return!0} +function LK(a,b,c,d,e,f){if(b=b.a){var g=[],h=[];var k=[];var l=b.i.length,m={};if(d.l){var n=dA(d,e);if(0==(n&4278190080))k=null;else{var p=d.s?eA(d,e):0;if(MK(a,b.key,c)){var q=VK(b,c);q.c=n>>24&255;q.f=p>>24&255}for(q=0;q<l;q++){var t=b.g&&q<Math.floor(l/2),v=(t?p:n)+b.i[q];if(f.has(v))var u=f.get(v);else m[v]?u=m[v]:(u=new pL(v),m[v]=u,t?h.push(q):g.push(q));k.push(u)}}}else k=null;b.b=k;if(0!=g.length||0!=h.length)if(MK(a,b.key,c)){for(a=0;a<g.length;a++)d=g[a],e=b.b[d],e.b=b.h[d],e.a=new pq(b.a[4* +d],b.a[4*d+1],b.a[4*d+2],b.a[4*d+3]),f.add(e);for(a=0;a<h.length;a++)d=h[a],e=b.b[d],e.b=b.h[d],e.a=new pq(b.a[4*d],b.a[4*d+1],b.a[4*d+2],b.a[4*d+3]),f.add(e)}else{c=b.b;for(p=n=k=0;p<h.length;p++)l=h[p],m=c[l],m.a=new pq(k,0,b.c[4*l+2],b.c[4*l+3]),k+=Math.ceil(b.c[4*l+2]);for(p=0;p<g.length;p++)l=g[p],m=c[l],m.a=new pq(n+k,0,b.c[4*l+2],b.c[4*l+3]),n+=Math.ceil(b.c[4*l+2]);l=k+n;m=b.height;n=vL(b,l,m,g,h);if(a=PK(a,n,e,d,0,0,l,m,b.g?k:void 0)){for(d=0;d<h.length;d++)l=h[d],m=c[l],m.b=a,f.add(m);for(h= +0;h<g.length;h++)l=g[h],m=c[l],m.b=a,f.add(m);f=!0}else f=!1;f||(b.b=null)}}}function NK(a,b,c){if(a.a){tL||(tL=go("canvas"));uL||(uL=go("canvas"));a=tL;tL=uL;uL=a;var d=a.getContext("2d");d.globalCompositeOperation="source-over";a.width<b||a.height<c?(a.width<b&&(a.width=b),a.height<c&&(a.height=c)):d.clearRect(0,0,b,c)}else a=uJ(tJ(),b,c);return a} +function vL(a,b,c,d,e){var f=a.b;sL||(sL=go("canvas"),sL.height=60);var g=sL;g.width<b&&(g.width=b);g.height<c&&(g.height=c);65536<g.width*g.height&&65536>=b*c&&(g.width=b,g.height=c);g=g.getContext("2d");g.clearRect(0,0,b,c);b=[e,d];for(c=0;c<b.length;c++)for(d=b[c],e=0;e<d.length;e++){var h=d[e],k=f[h];g.drawImage(a.h[h],a.a[4*h],a.a[4*h+1],a.a[4*h+2],a.a[4*h+3],k.a.left,k.a.top,k.a.width,k.a.height)}return sL} +function PK(a,b,c,d,e,f,g,h,k){if(!d.l)return null;var l=OH(dA(d,c));a=NK(a,g,h);var m=a.getContext("2d");k?(m.fillStyle=OH(eA(d,c)),m.fillRect(0,0,k,h),m.fillStyle=l,m.fillRect(k,0,g-k,h)):(m.fillStyle=l,m.fillRect(0,0,g,h));m.globalCompositeOperation="destination-in";m.drawImage(b,e,f,g,h,0,0,g,h);return a};function wL(a,b,c,d,e){this.key=a;this.c=b;this.a=c;this.b=d;this.la=e};function xL(a,b,c,d){this.text=a;this.width=b;this.a=c;this.b=d};function yL(a,b,c,d){this.j=new rL(d);this.h=b;this.a=a;this.i=d;this.b=[];this.g=!1;this.c=2*c;this.f=c}var zL=null; +yL.prototype.Rc=function(){if(!this.g){var a=this.a.a;if(Jy(a)&&py(Ky(a))){a=Ky(a).a;for(var b=0;b<a.length;b++){var c=a[b];if(null!=c.c||null!=c.b&&gu(Eu(c))){var d=b;c=Cu(c).a;for(var e=0;e<c.length;++e){var f=c[e],g=AL(this.a,d,0,e);if(tu(f)){var h=f;f=g;g=""+f;var k=uu(h);ou(h);var l=h.a?h.a.length:0;var m=k+l,n=[],p=[],q=Array(4*m),t=Array(m);t[0]=0;m=Array(4*m);BL(this.a);for(var v=0,u=0;u<l;++u){var w=u;if(null!=h.l||null!=h.s){var y=h;var A=u;qu(y);y=y.l[A]/8}else y=0;A=h;var z=u;ou(A);w= +CL(this,A.a[z],w,y,n,p,q,t,m);v=v>w.height?v:w.height}for(u=z=A=0;u<k;++u)w=u+l,y=wu(h)?xu(h,u)/8:0,w=CL(this,vu(h,u),w,y,n,p,q,t,m),z=z>w.Se?z:w.Se,A=A>w.height?A:w.height,v=v>w.height?v:w.height;l=new oL(z/this.c,A/this.c);l.a=new mL(g,Math.ceil(v),n,p,q,t,m,this.c,null!=h.a||null!=h.j?!0:!1);this.b[f]=l}else null!=f.b&&(h=g,f=su(f),n=CK(this.h,h),p=this.a.getZoom(),g=hA(n,p),n=gA(n,p),p=DL(this,f,g,n),q=new oL(p,g),q.f=new xL(f,p,g,n),this.b[h]=q)}}else if(null!=c.b)for(d=c,c=b,e=this.a.getZoom(), +h=null!=d.a?2:1,f=0;f<h;++f)for(g=0==f?Cu(d).a:Du(d).a,n=0;n<g.length;++n)if(q=g[n],p=AL(this.a,c,f,n),t=CK(this.h,p),!fA(t,e))if(tu(q)){l=q;k=this.a.a;q=vu(l,0);q=ay(Dy(k),q);q=new pq(Vx(q),Wx(q),Xx(q),Yx(q));t=null;if(null!=l.a||null!=l.j)ou(l),t=l.a[0],t=ay(Dy(k),t),t=new pq(Vx(t),Wx(t),Xx(t),Yx(t));k=q.width/this.f;m=q.height/this.f;l=BL(this.a);l.Qb()&&l.Ib(3);k=new oL(k,m);k.g=new wL("restyle_index"+p,l.Ab(),q,t,this.f);this.b[p]=k}else null!=q.b&&(l=t,q=su(q),k=this.a.getZoom(),t=hA(l,k),l= +gA(l,k),k=DL(this,q,t,l),m=new oL(k,t),m.f=new xL(q,k,t,l),this.b[p]=m)}this.g=!0}}};function CL(a,b,c,d,e,f,g,h,k){var l=EL(a.a,b),m=BL(a.a);d=1E4<d||0>d?0:d;var n=ay(Dy(a.a.a),b);b=Xx(n);var p=Yx(n),q=d*a.c+b;e.push(l);f.push(m.Ab());g[4*c]=Vx(n);g[4*c+1]=Wx(n);g[4*c+2]=Xx(n);g[4*c+3]=Yx(n);e=c+1;e<h.length&&(h[e]=h[c]+b);k[4*c]=d*a.c;k[4*c+1]=0;k[4*c+2]=b;k[4*c+3]=p;return{height:p,Se:q}} +function DL(a,b,c,d){a=qL(c,d,a.i);zL||(c=go("canvas"),c.width=c.height=128,zL=c.getContext("2d"));c=zL;c.font!=a&&(c.font=a);return Math.ceil(c.measureText(b).width)}yL.prototype.Tb=function(a){return this.b[a]||null};function FL(a,b,c){this.b=a;this.c=b;this.a=c;this.a.sort(nK)};function GL(){this.a=[];this.b=0};function HL(a){mK.call(this,a);this.b=this.h=this.i=this.v=0}F(HL,mK);function IL(a,b,c,d){var e=a.label.a,f=JJ(e,b),g=KJ(e,b),h=JJ(e,c),k=KJ(e,c),l=a.f;if(l){b=e.i[Math.floor(b)];c=e.i[Math.ceil(c)];var m=h-f,n=k-g,p=Math.sqrt(m*m+n*n);e=-n/p;var q=m/p;m/=p;n/=p;f=f+e*l-m*l*b;g=g+q*l-n*l*b;h=h+e*l+m*l*c;k=k+q*l+n*l*c}return cK(d,f,g,h,k,a.m()+2*a.v,a)}HL.prototype.A=function(){var a=this.label.a,b=SK(a.c,a.f),c=this.b,d=b+c+this.u();this.i=EK(a.c,b+c);this.h=EK(a.c,d)}; +HL.prototype.s=function(a){for(var b=[],c=this.h,d=this.i;d<c;d=Math.floor(d+1))b.push(IL(this,d,Math.min(Math.floor(d+1),c),a));return b}; +HL.prototype.l=function(a){var b=this.i,c=this.h,d,e,f=this.label.a;var g=d=JJ(f,b);var h=e=KJ(f,b);for(var k=Math.floor(b+1);k<c;++k){b=JJ(f,k);var l=KJ(f,k);g=Math.min(b,g);d=Math.max(b,d);h=Math.min(l,h);e=Math.max(l,e)}b=JJ(f,c);l=KJ(f,c);g=Math.min(b,g);d=Math.max(b,d);h=Math.min(l,h);e=Math.max(l,e);c=this.m()/2+Math.abs(this.f);a.left=g-c;a.right=d+c;a.top=h-c;a.bottom=e+c};function JL(){HL.call(this,2);this.g=!1}F(JL,HL);JL.prototype.m=function(){return this.c.height};JL.prototype.u=function(){return this.c.width}; +function KL(){HL.call(this,0);this.height=this.width=0}F(KL,HL);KL.prototype.m=function(){return this.height};KL.prototype.u=function(){return this.width};function LL(a,b){HL.call(this,5);this.g=a;this.j=b}F(LL,HL);LL.prototype.m=function(){return this.j.height};LL.prototype.u=function(){return this.j.width};function FK(a){var b=a.label.a,c=SK(b.c,b.f),d=a.b+a.j.width/2;return 1==b.h&&lK(a.label)?c-d:c+d}function ML(a){mK.call(this,a);this.height=this.width=this.b=this.oa=0}F(ML,mK); +ML.prototype.s=function(a){var b=this.label.b;return[cK(a,b.screenX+this.oa,b.screenY+this.b,b.screenX+this.oa+this.width,b.screenY+this.b,this.height,this,this.label.l||this.label)]};ML.prototype.l=function(a){var b=this.label.b;a.left=b.screenX+this.oa;a.right=b.screenX+this.oa+this.width;a.top=b.screenY+this.b-this.height/2;a.bottom=b.screenY+this.b+this.height/2}; +function NL(a,b,c){ML.call(this,4);this.oa=b.left;this.b=b.top+b.height/2;this.width=b.width;this.height=b.height;this.g=a;this.h=b;this.text=c||""}F(NL,ML);function OL(){ML.call(this,3)}F(OL,ML);function PL(){ML.call(this,1);this.j=null;this.i=this.h=this.g=this.m=0}F(PL,ML);var QL={RIGHT:0,TOP:1,BOTTOM:2,LEFT:3}; +PL.prototype.s=function(a){var b=this.label.b,c=b.screenX+this.oa,d=b.screenX+this.oa+this.width,e=b.screenY+this.b-this.height/2;b=b.screenY+this.b+this.height/2;0<this.g&&(3==this.h?c-=this.g:0==this.h?d+=this.g:1==this.h?e-=this.g:2==this.h&&(b+=this.g));d+=this.i;b+=this.i;var f=(e+b)/2;return[cK(a,c,f,d,f,b-e,this,this.label.l||this.label)]}; +PL.prototype.l=function(a){var b=this.label.b;a.left=b.screenX+this.oa;a.right=b.screenX+this.oa+this.width+this.i;a.top=b.screenY+this.b-this.height/2;a.bottom=b.screenY+this.b+this.height/2+this.i;0<this.g&&(3==this.h?a.left-=this.g:0==this.h?a.right+=this.g:1==this.h?a.top-=this.g:2==this.h&&(a.bottom+=this.g))};function RL(a,b,c){this.a=b;this.c=this.b=0;this.h=[];this.f=[];this.g=!1;var d=0,e=0,f=0,g=0;a:{if(a=a.f)for(var h=0;h<a.length;h++)if(30511227==a[h].c){a=!0;break a}a=!1}a=a?0:2;for(h=0;h<b.length;++h){var k=new SL;k.a=g;k.b=e;this.f.push(k);d=Math.max(d,b[h].height);e+=b[h].width;c[h]||h==b.length-1?(k=new TL,k.b=d,k.lineWidth=e,k.a=f,this.h.push(k),this.c+=d,this.b=Math.max(this.b,e),f=this.c,e=d=0,g+=1):e+=a}}function TL(){this.a=this.b=this.lineWidth=0}function SL(){this.b=this.a=0};function UL(a,b,c,d,e){this.b=a;this.a=Array(2*a.a.length);a=this.b;var f=d[0],g=d[1],h=d[2];d=d[3];var k=e.x;e=e.y;for(var l=0;l<a.a.length;++l){var m=a.a[l],n=a.f[l],p=a.h[n.a],q=p.b-m.height;this.a[2*l+1]=p.a+.5*q+m.height/2}switch(c){case 2:m=0;break;case 3:m=1;break;default:m=.5}for(l=0;l<a.f.length;++l)n=a.f[l],p=a.h[n.a],q=a.b-p.lineWidth,this.a[2*l]=n.b+q*m;switch(b){case 7:case 11:case 15:k=g+k;break;case 6:case 10:case 14:k=d-a.b-k;break;default:k=a.b/-2}if(9==b||13==b)l=(g-d)/2,2==c?(k= +d-l,e=0):3==c&&(k=g+l-a.b,e=0);switch(b){case 9:case 10:case 11:b=f-a.c-e;break;case 13:case 15:case 14:b=h+e;break;default:b=a.c/-2+(f+h)/2}for(l=0;l<this.a.length;l+=2)this.a[l]+=k,this.a[l+1]+=b}function VL(a,b){for(var c=a.b,d=0,e=0,f=0;f<c.a.length;++f){var g=a.a[2*f+1]-c.a[f].height/2,h=a.a[2*f];if(0==f||g<d)d=g;if(0==f||h<e)e=h}a=d+c.c;c=e+c.b;b[0]=d;b[1]=c;b[2]=a;b[3]=e};function WL(a){this.data=a||[]}F(WL,W);WL.prototype.Gb=function(a){this.data[4]=a};function XL(){this.a=Array(4);this.b=new WH(0,0)}var nA=new fo(0,0),YL=new WH(1,0);function ZL(a,b){b=b.c;var c=Fu(a);null!==c.g?a=Zc(c.g):c.j&&null!=c.a&&null!=c.i?(a=Zc(c.j,c.a,c.i-c.a),a.ca(),a.ca()):a=Zc();c=null!=c.f?null==c.f?0:c.f:BI(a);var d=new Float32Array(2*c);DI(a,c,b,d);Vc(a);return d}function $L(a){var b;if(b=null!=a.c?!0:!1)b=null!=Fu(a).c?!0:!1;b?(a=Fu(a),a=(null==a.c?0:a.c)/8):a=0;return a} +function aM(a){var b;if(b=null!=a.c?!0:!1)b=null!=Fu(a).b?!0:!1;b?(a=Fu(a),a=(null==a.b?0:a.b)/8):a=0;return a}function bM(a){for(var b=0;b<Fe(a,1);b++){var c=b;if(31==Ce(a,1)[c])return!0}return!1} +function cM(a,b,c,d,e,f){var g=e.data,h=e.a.f,k=g.getZoom(),l=dM(e,b,c);if(IF()){var m=eM(g,l.J);m&&(m=new WL((new fM(m.data[8])).data[0]),bM(m))&&(l.B=!0)}l.b=new TJ(d.x,d.y);m=CK(h,g.b.a[4][c].ka());if(m.a&&m.a[k]&&null!=m.a[k].i)if(m.a&&m.a[k]&&null!=m.a[k].i){var n=m.a[k];n=null==n.i?1:n.i}else n=1;else n=Eu(b),n=null==n.c?1:n.c;var p=n;n=g.b.a[4][c].j;var q=CK(h,n),t=q.j,v=!1,u=-1,w=null;null!=b.a&&(u=g.b.a[4][c].l,w=CK(h,u),v=w.j);g=gM(b,c,e,l,t||v);var y=g[0];g=g[1];var A=hM(e,b);t&&(A||(A= +new WH(0,0)),iM(p,k,q,A));h=a.a;A?(h[0]=A.y,h[1]=A.x,h[2]=A.y,h[3]=A.x):(h[0]=0,h[1]=0,h[2]=0,h[3]=0);p=jM(p);h=new UL(y,p,mu(Cu(b)),h,kM(a,m,k));if(g){var z=a.a;VL(h,z);m=lM(a,m,k);z=new UL(g,mM(b,f),mu(Du(b)),z,m)}t&&nM(a,y,h,q,k,n);v&&nM(a,g,z,w,k,u);f=y.a;for(a=0;a<f.length;++a)eK(l,f[a]);y.g&&(l.u=!0);a=!1;g&&(a=!0,k=null==b.g?0:b.g,f=k&1?k&2?2:1:0,k=k&16?0:k&2?2:1,(m=0!=f)||1!=k||(a=!1),f==k&&m&&(a=!1));if(a){b=dM(e,b,c,!0);b.b=new TJ(d.x,d.y);b.l=l;l.G=b;d=g.a;for(a=0;a<d.length;++a)eK(b,d[a]); +g.g&&(b.u=!0);oM(l,h);oM(b,z);b.i=l.i;l.B&&(b.B=!0);pM(e,l);pM(e,b)}else{if(g){d=g.a;for(a=0;a<d.length;++a)eK(l,d[a]);g.g&&(l.u=!0)}oM(l,h,z);pM(e,l)}}function hM(a,b){b=fu(Eu(b));if(null!=b.b||null!=b.a){a=a.data.c;null!==b.b?b=Zc(b.b):b.f&&null!=b.a&&null!=b.h?(b=Zc(b.f,b.a,b.h-b.a),b.ca(),b.ca()):b=Zc();var c=b.da()/a;a=b.da()/a;Vc(b);return new WH(c,a)}return null} +function iM(a,b,c,d){var e=jA(c,b);if(e&&0==d.x&&0==d.y)switch(a){case 2:d.x=-e;d.y=0;break;case 3:d.x=e;d.y=0;break;case 4:d.x=0;d.y=-e;break;case 5:d.x=2*e;d.y=-e;break;case 6:d.x=2*-e;d.y=-e;break;case 7:d.x=0;d.y=e;break;case 8:d.x=2*e;d.y=e;break;case 9:d.x=2*-e,d.y=e}if((b=mA(c,b))&&(b.width||b.height)){switch(a){case 5:case 2:case 8:d.x-=b.width;break;case 6:case 3:case 9:d.x+=b.width}switch(a){case 5:case 4:case 6:d.y-=b.height;break;case 8:case 7:case 9:d.y+=b.height}}} +function dM(a,b,c,d){var e=a.data,f=null==b.g?0:b.g;f=d?f&16?0:f&2?2:1:f&1?f&2?2:1:0;d=new dK;d.g=null==b.m?0:b.m;d.J=e.b.a[4][c].ka();d.H=null==b.g?0:b.g;d.wb=f;d.C=!a.a.s;d.uc=a.a.Pa;a=e.getZoom();null!=b.h&&(d.m=a+(null==b.h?0:b.h)/8);null!=b.o&&(d.K=a+(null==b.o?0:b.o)/8);return d}function pM(a,b){b.h=a.a.j.length;var c=a.data,d=22-c.getZoom(),e=32767-b.g;b.v=(b.l?1:0)|(tK(c)&1)<<1|(uK(c)&1)<<2|(d&31)<<3|(e&32767)<<8|(0!=b.wb?0:8388608);a.a.j.push(b)} +function gM(a,b,c,d,e){var f=c.data,g=nI(wy(f.a)),h=c.a.f,k=f.getZoom();c=c.a.Y;for(var l=null!=a.a?2:1,m=Array(l),n=!1,p=!1,q=!1,t=0;t<l;++t){for(var v=0==t?Cu(a):Du(a),u=[],w=[],y=0;y<(v.a?v.a.length:0);++y){var A=v.a[y],z;(z=y+1==(v.a?v.a.length:0))||(z=v.a[y+1],z=null==z.o?!1:z.o);var C=AL(f,b,t,y),I=CK(h,C),S=fA(I,k);if(S)p=su(A),A=S.b||g,I=$s(S,A,p),S=at(S,A,p),p=new NL(I,S,p),p.a=C,C=p,p=!0,u.push(C),w.push(z);else if(tu(A)||null!=A.b)if(S=c.Tb(C),0!=S.width&&0!=S.height){A=S;var ca=new OL; +ca.a=C;ca.height=A.height;ca.width=A.width;ca.c=A;A=ca;I.j?(q=!0,ca=mA(I,k),C=qM(S.width,S.height,jA(I,k),lA(I,k),ca,Tz(I.b,8),C),u.push(C),w.push(z),C.j=A,255!=(Uz(I,0)>>24&255)&&(n=!0)):(u.push(A),w.push(z))}}m[t]=new RL(a,u,w)}d.i=p&&!q&&!e;n&&(d.u=!0);return m}function jM(a){switch(a){case 2:return 6;case 3:return 7;case 4:return 9;case 5:return 10;case 6:return 11;case 7:return 13;case 8:return 14;case 9:return 15}return 5}function kM(a,b,c){if(!kA(b,c))return YL;a=a.b;a.x=0;a.y=0;return a} +function lM(a,b,c){if(!kA(b,c))return YL;kA(b,c)?(b=b.a[c],b=(null==b.l?0:b.l)/8):b=0;a=a.b;a.x=b;a.y=b;return a}function mM(a,b){switch(null==a.v?9:a.v){case 6:return 6;case 9:return 7;case 2:return 9;case 1:return 10;case 3:return 11;case 13:return b?9:13;case 12:return b?10:14;case 14:return b?11:15}return 5}function qM(a,b,c,d,e,f,g){var h=new PL;h.m=f;h.g=c;h.i=d;h.width=a+2*e.width+2*f;h.height=b+2*e.height+2*f;h.a=g;return h} +function oM(a,b,c){for(var d=a.c,e=null,f=0;f<d.length;f++){var g=b,h=0;f>=b.a.length/2&&(g=c,h=-(b.a.length/2));var k=d[f];k.oa=g.a[2*(f+h)];k.b=g.a[2*(f+h)+1];4==k.type?(g=k,g.h.top=k.b-g.h.height/2,g.h.left=k.oa):1==k.type&&(g=k,h=QL,g.g&&(g.h=0<k.oa?h.LEFT:0>k.oa+k.width?h.RIGHT:0<k.b-k.height/2?h.TOP:h.BOTTOM),g.j&&(h=g.j,h.oa=k.oa+(k.width-h.width)/2,h.b=k.b,g.j=null,e||(e=[]),e.push(h)))}if(e)for(f=0;f<e.length;f++)eK(a,e[f])} +function rM(a,b,c){var d=c.data,e=nI(wy(d.a)),f=d.getZoom(),g=c.a.f;c=c.a.V;for(var h=0,k=0;k<a.length;++k){var l=AL(d,b,0,k),m=fA(CK(g,l),f);if(m)l=at(m,m.b||e),0==k&&(h+=2),h+=l.width;else{l=c.Tb(l);if(!l)return-1;h+=l.width}}return h+=2*(a.length-1)}function sM(a,b,c,d,e,f){e=new LL(e,f);e.i=0;e.h=b;e.b=d;e.a=a;e.f=c;return e}function tM(a,b,c,d,e,f){var g=new JL;g.i=0;g.h=b;g.c=e;g.g=f;c&&!f&&(g.v=-2);g.a=a;g.f=c;g.b=d;return g} +function uM(a,b,c,d,e,f){var g=new KL;g.i=0;g.h=b;g.width=e;g.height=f;g.a=a;g.b=c;g.f=d;return g}function nM(a,b,c,d,e,f){a=a.a;VL(c,a);var g=a[1]-a[3],h=a[2]-a[0],k=mA(d,e),l=Tz(d.b,8),m=a[0]+(a[2]-a[0])/2;c.a.push(a[3]-k.width-l);c.a.push(m);c=qM(g,h,jA(d,e),lA(d,e),k,l,f);b.a.push(c);255!=(Uz(d,0)>>24&255)&&(b.g=!0)};function vM(a){this.Nb=a;this.u=new XL} +vM.prototype.b=function(a){if(a.data.g&&(this.j(a),!a.a.Qa)){var b=a.data.a;if(Jy(b)&&py(Ky(b))){var c=Ky(b).a,d=a.data.c;for(b=0;b<c.length;b++){var e=c[b];if(null!=e.b){var f=Eu(e);if(!gu(f)){f=au(fu(f));var g=f.da()/d,h=f.da()/d;Vc(f);0>g||256<g||0>h||256<h||cM(this.u,e,b,new eo(g,h),a,this.Nb)}}}c=a.a.j;d=a.N.getZoom();c.sort(fK);e=0;f=c.length/2;for(b=g=0;b<c.length-1;b++){h=c[b];var k=d-e;0<k&&0==h.m&&(h.m=k);g++;g>=f&&(e++,f/=2,g=0)}}wM(a);d=a.a.j;b=new GL;c=!0;for(e=0;e<d.length;++e){f=d[e]; +g=f.c;for(h=0;h<g.length;h++){k=b;var l=g[h],m=l.type;k.a[m]=k.a[m]||[];k.a[m].push(l);l.o=k.b++}2!=f.wb&&(c=!1)}a.a.j.sort(fK);d=[];for(e=0;e<b.a.length;++e)if(b.a[e]){f=e;g=[];h=[];for(k=0;k<b.a[e].length;++k)l=b.a[e][k],l.label.u?h.push(l):g.push(l);g.length&&(g.sort(nK),d.push(new FL(0,f,g)));h.length&&(h.sort(nK),d.push(new FL(1,f,h)))}a.a.v=d;a.a.Ga=!c;this.g(a)}a.a.Qa=!0};vM.prototype.g=sa; +function wM(a){var b=a.data.a;if(Jy(b)&&py(Ky(b))){b=Ky(b).a;for(var c=0;c<b.length;c++){var d=b[c];if(null!=d.c)a:{var e=d,f=c;d=a;var g=d.data,h=wy(g.a),k=d.a.f,l=ZL(e,g),m=new dL(l),n=m.a,p=SK(m.b,n-1),q=Cu(e).a;l=rM(q,f,d);if(-1!=l){var t=Fu(e);var v=null==t.h?1:t.h;var u=aM(e);t=$L(e);h=nI(h);var w=g.getZoom(),y=d.a.V;e=dM(d,e,f);e.a=m;e.a.h=v;e.m<w&&(e.m=w);var A=n-1,z=0;switch(v){case 2:z=u;e.a.f=0;break;case 1:z=-l/2;e.a.f=EK(m.b,p/2);break;case 3:e.a.f=n-1,z=-l-u}for(p=m=n=0;p<q.length;++p){v= +AL(g,f,0,p);var C=fA(CK(k,v),w);if(C){var I=C.b||h;u=$s(C,I);C=at(C,I);I=C.height;m=I>m?I:m;0==p&&(n+=2);v=sM(v,A,t,z+n,u,C);eK(e,v);n+=C.width}else{u=y.Tb(v);if(0==u.width||0==u.height)break a;I=u.height;m=I>m?I:m;v=tM(v,A,t,z+n,u,!1);eK(e,v);n+=u.width}n+=2}f=g.b.a[4][f].j;CK(k,f).j&&(k=uM(f,A,z,t,l,m),eK(e,k),e.C=!1);pM(d,e)}}else if(null!=d.b&&gu(Eu(d)))a:{h=d;d=c;k=a;f=k.a.V;g=k.data;l=g.getZoom();q=k.a.f;t=nI(wy(g.a));y=w=0;e=Cu(h).a;for(A=0;A<e.length;++A){z=AL(g,d,0,A);m=CK(q,z);if(m=fA(m, +l))n=m.b||t,n=at(m,n),m=n.height,z=n.width;else{n=f.Tb(z);if(!n)break a;m=n.height;z=n.width}w+=m;z>y&&(y=z)}z=g.c;m=Eu(h);n=au(fu(m));A=n.da()/z;z=n.da()/z;Vc(n);if(!(0>A||256<A||0>z||256<z)){m=null==m.b?0:m.b;n=(y+1)/Math.pow(2,(null==h.h?0:h.h)/8);y=n*Math.cos(m*Math.PI/1800)/2;m=n*Math.sin(m*Math.PI/1800)/2;n=new Float32Array(4);n[0]=A-y;n[1]=z-m;n[2]=A+y;n[3]=z+m;y=new dL(n);w=-w/2;h=dM(k,h,d);h.a=y;h.a.f=EK(y.b,SK(y.b,y.a-1)/2);for(A=0;A<e.length;++A)z=AL(g,d,0,A),m=CK(q,z),(m=fA(m,l))?(n=m.b|| +t,y=$s(m,n),n=at(m,n),m=n.height,w+=m/2,p=-n.width/2,y=sM(z,1,w,p,y,n),eK(h,y),w+=m/2):(n=f.Tb(z),w+=n.height/2,p=-n.width/2,y=tM(z,1,w,p,n,!0),eK(h,y),w+=n.height/2);pM(k,h)}}}}};function xM(a){if(a.a&&!(a.H&8)){for(var b=a.a,c=b.a-1,d=0,e=0;e<a.c.length;++e){var f=a.c[e];f.i<c&&(c=f.i);f.h>d&&(d=f.h)}a.A=Math.abs(Math.atan2(KJ(b,d)-KJ(b,c),JJ(b,d)-JJ(b,c))-.02)>Math.PI/2}};function yM(a,b){vM.call(this,!1);this.c=a;this.a=b}F(yM,vM);yM.prototype.j=function(a){a.a.Y||(a.a.Y=a.a.V=new yL(a.data,a.a.f,this.c,this.a));a.a.Y.Rc()};yM.prototype.g=function(a){a=a.a.j;for(var b=0;b<a.length;++b)xM(a[b])};function zM(a,b,c,d,e,f,g){this.context=a.getContext("2d");this.canvas=a;this.x=b;this.y=c;this.width=d;this.height=e;this.a=0!=b||0!=c||d!=a.width||e!=a.height;this.b=f;this.c=g}function AM(a,b,c){c/=a.c;var d=Math.floor(a.width),e=Math.floor(a.height);a.a?b.drawImage(a.canvas,a.x,a.y,d,e,0,0,d*c,e*c):b.drawImage(a.canvas,0,0,d*c,e*c)}function BM(a){a.a&&a.b&&a.b.c(a)};function CM(a){this.a=a}CM.prototype.c=function(){};CM.prototype.f=function(a,b){var c=pF(2,this.a);a*=c;b*=c;var d=go("CANVAS");d.width=a;d.height=b;d.getContext("2d").scale(c,c);return new zM(d,0,0,a,b,this,this.a)};function DM(a){this.g=[];this.b=[];this.a=a}DM.prototype.c=function(a){var b=pF(2,this.a);a.context.clearRect(a.x/b,a.y/b,a.width/b,a.height/b);this.b.push(a)};DM.prototype.f=function(a,b){if(0==this.b.length){var c=go("CANVAS"),d=pF(2,this.a);c.width=1536*d;c.height=1024*d;this.g.push(c);c.getContext("2d").scale(d,d);for(var e=0;4>e;e++)for(var f=0;6>f;f++){var g=new zM(c,256*d*f,256*d*e,256*d,256*d,this,this.a);this.b.push(g)}}c=pF(2,this.a);a*=c;b*=c;c=this.b.pop();c.width=a;c.height=b;return c};function EM(){}F(EM,Error);function FM(){this.a="pending";this.f=[];this.c=this.g=void 0}UC(FM);function GM(){Ja.call(this,"Multiple attempts to set the state of this Result")}F(GM,Ja);r=FM.prototype;r.getState=function(){return this.a};r.na=function(){return this.g};r.getError=function(){return this.c};r.wait=function(a,b){"pending"==this.a?this.f.push({qc:a,scope:b||null}):a.call(b,this)};function HM(a,b){if("pending"==a.a)a.g=b,a.a="success",IM(a);else if(!JM(a))throw new GM;} +function KM(a,b){if("pending"==a.a)a.c=b,a.a="error",IM(a);else if(!JM(a))throw new GM;}function IM(a){var b=a.f;a.f=[];for(var c=0;c<b.length;c++){var d=b[c];d.qc.call(d.scope,a)}}r.cancel=function(){return"pending"==this.a?(KM(this,new EM),!0):!1};function JM(a){return"error"==a.a&&a.c instanceof EM}r.then=function(a,b,c){var d,e,f=new WC(function(a,b){d=a;e=b});this.wait(function(a){JM(a)?f.cancel():"success"==a.getState()?d(a.na()):"error"==a.getState()&&e(a.getError())});return f.then(a,b,c)};function LM(a,b,c){a.wait(b,c)}function MM(a,b,c){LM(a,function(a){"success"==a.getState()&&b.call(c,a.na(),a)},c)}function NM(a,b){var c=new OM([a]);LM(a,function(a){"success"==a.getState()?HM(c,b(a.na())):KM(c,a.getError())});return c}function PM(a,b,c){var d=new OM([a]);LM(a,function(a){"success"==a.getState()?(a=b.call(c,a),d.b.push(a),LM(a,function(a){"success"==a.getState()?HM(d,a.na()):KM(d,a.getError())})):KM(d,a.getError())});return d} +function QM(a){function b(){"pending"==e.getState()&&Qa(d,c)&&HM(e,d)}function c(a){return"pending"!=a.getState()}var d=Va(arguments),e=new OM(d);Ma(d,function(a){a.wait(b,void 0)});return e}function RM(a){function b(a){return"success"==a.getState()}var c=Va(arguments),d=new OM(c);LM(QM.apply(QM,c),function(a){a=a.na();Qa(a,b)?HM(d,a):KM(d,a)});return d}function OM(a){FM.call(this);this.b=a}F(OM,FM);function SM(a){this.f=a}function TM(a,b){if(!b.data||UM(b.data))return!0;for(;"success"==a.Od(b).getState(););return a.Ub(b)}function VM(a,b){function c(){0==--d&&(g&&g(),HM(f,!0))}for(var d=0,e=Ss.sc(),f=new FM,g=null,h=0;h<b.length;h++){var k=b[h];Ts(e,k)||(g=g||a.f(),d++,Us(e,k,c))}0==d&&HM(f,!0);return f} +function WM(a,b){var c=b.data;b=b.a.f;var d=c.a;if(Jy(d)&&py(Ky(d))){var e=nI(wy(d)),f=c.getZoom();c=c.b;var g={};d=Ky(d).a;for(var h=0;h<d.length;++h)for(var k=d[h],l=c.a[4][h],m=null!=k.a?2:1,n=0;n<m;++n){var p=0==n?Cu(k):Du(k);if(null!=p.a){p=p.a;for(var q=0;q<p.length;++q){var t=XM(l,n,q);(t=fA(CK(b,t),f))&&t.a&&(t=Xs(t,e,su(p[q])),g[t]=!0)}}}b=Object.keys(g)}else b=[];return VM(a,b)};var YM=null,ZM=null;function $M(){YM||(YM=new FM,HM(YM,!0));return YM}function aN(){ZM||(ZM=new FM,KM(ZM));return ZM}function bN(a,b,c){LM(a,function(a){JM(a)||b.call(this,a)},c)}function cN(a){if(JM(a)){var b=!1;a=a.b;for(var c=0;c<a.length;c++)b|=a[c].cancel()}}function dN(a){function b(){"pending"==d.getState()&&HM(d,c)}if(1==arguments.length)return arguments[0];var c=Va(arguments),d=new FM;Ma(c,function(a){a.wait(b,void 0)});return d};function eN(a,b,c,d,e,f){this.f=f.o;this.j=a;this.h=b;this.l=c;this.g=e;(a=fN[d])?d=a:(a=pb?new DM(d):new CM(d),d=fN[d]=a);this.i=d;this.a=[this.gf,this.Ad,this.Wd,this.qf,this.Le,this.Qe,this.Me];this.b=this.a.indexOf(this.Ad);this.c=this.a.indexOf(this.Wd)}F(eN,SM);var gN=$M(),hN=aN(),fN={};function iN(a,b){b=b.a;b.i.length||(b.i=Array(a.a.length))}r=eN.prototype; +r.Od=function(a){iN(this,a);for(var b=a.a,c=0;c<this.a.length;++c){var d=b.i[c];if(!d){d=this.a[c];if(d==this.Le||d==this.Qe||d==this.Me){var e="success"==b.i[this.c].getState(),f="success"==b.i[this.b].getState();if(!e||!f)continue}b.i[c]=d.call(this,a);return gN}}a=[];for(c=0;c<this.a.length;++c)(d=b.i[c])&&"pending"==d.getState()&&a.push(d);return a.length?dN.apply(null,a):hN};r.Ub=function(a){for(var b=0;b<this.a.length;++b){var c=a.a.i[b];if(!c||"success"!=c.getState())return!1}return!0}; +r.Wd=function(a){function b(){0==--c.l&&HM(d,!0)}var c=a.a;c.l=0;var d=new FM;c.l+=jN(a,b);c.l+=kN(a,b);a=a.b;if(a){var e=a.a;iN(this,a);var f=e.i[this.c];f||(f=this.Wd(a),e.i[this.c]=f)}return f&&"pending"==f.getState()?c.l?RM(f,d):f:c.l?d:gN};function jN(a,b){var c=a.data.a;a=a.data.j;for(var d=null!=c.a&&ry(Ly(c))?Ly(c).Aa:[],e=0,f=0;f<d.length;f++){var g=eJ(a,c,f);g&&(e+=lN(g,b))}return e}function kN(a,b){var c=0;a=a.data;null!=a.a.h&&(a=BL(a),c+=lN(a,b));return c} +r.Ad=function(a){var b=WM(this,a);a=a.b;if(a){var c=a.a;iN(this,a);var d=c.i[this.b];d||(d=this.Ad(a),c.i[this.b]=d)}return d&&"pending"==d.getState()?"pending"==b.getState()?RM(d,b):d:"pending"==b.getState()?b:gN};r.gf=function(a){var b=a.a;if(a.b){var c=a.b,d=a.N.ba().c,e=PB(this.g,d),f=c.data.i;f.length&&TA(e,f);this.gf(c)}b.f||(c=a.data.m,d=a.N.ba().c,e=PB(this.g,d),f=a.data.i,f.length&&TA(e,f),SA(e,c),d=mN(a.data,d,e),b.f=d,a.data.s=d,nN(a.data));return gN};r.qf=function(a){oN(this,a);return gN}; +r.Le=function(a){a.a.j.length||this.h.b(a);(a=a.b)&&this.h.b(a);return gN}; +function pN(a,b){var c=b.a.j;if(c.length&&b.a.f)for(var d=0;d<c.length;d++)for(var e=a.l,f=c[d],g=b,h=b.a.f,k=0;k<f.c.length;k++){var l=f.c[k];switch(l.type){case 3:zK(e,l.c,g.a.Y,h,l,g.data.getZoom());break;case 2:var m=e,n=l,p=h,q=n.c,t=g.a.V;l=g.data.getZoom();var v=lK(n.label);zK(m,q,t,p,n,l);var u=q.a;t=u&&u.b;var w=!!q.canvas||!!q.b||!!q.c;if(u&&(w||t)){var y=null;w&&!t&&(y=AK(q));if(y||t)for(t=GK(p,n.a),p=SH(p,n.a),w=n.f,v&&n.g&&(w*=-1),q=HK(u,y,q.b),y=w,m.c&&!m.f&&(m.f=new wJ),u=n.c,m.a.reset(), +TK(n,v,y,m.a),n=0;n<m.a.b;n++)UK(m,t,p,l,u,q,m.a.a[6*n+4],m.a.a[6*n+5])}}}}r.Me=function(a){pN(this,a);a.b&&pN(this,a.b);return gN};r.Qe=function(a){return qN(this,a)?gN:null};function lN(a,b){a.Qb()&&a.Ib(3);return!a.Db()&&!a.bc()||0==a.Ab().src.length?(ec(a.Ab(),"load",function(){b()}),!0):!1} +function qN(a,b,c){if(b.a.s||4==b.N.Ea())return!0;var d=b.a.rc;if(0<d.h||1!=d.b.length)var e=null;else e=d.b[0],1!=e.type?e=null:(d.h=1,e=dJ(gJ(d.a,e.type,e.b)));if(e)return b.a.Ia=e,!0;e=b.a.D;e||(e=a.i.f(256,256),b.a.D=e);a=e;if(a.a){a.context.save();a.context.setTransform(1,0,0,1,a.x,a.y);a.context.beginPath();a.context.rect(0,0,a.width,a.height);a.context.clip();var f=pF(2,a.c);a.context.scale(f,f)}a=e.context;b=b.data.getZoom();f=25;c&&(kJ(d),f=-1);lJ(d,a,1,b,f);e.a&&e.context.restore();return d.b.length== +d.h&&null==d.f&&null==d.g}function oN(a,b){if(!b.a.rc){var c=b.a;a=a.j;a=new jJ(a.Ra,a.La,a.Qa,b);c.rc=a}return b.a.rc};function rN(a,b){this.start=a<b?a:b;this.a=a<b?b:a};function sN(){this.f=[];this.g=[];this.a=[];this.h=[];this.lng=this.lat=this.c=this.b=0;for(var a=256,b=0;21>b;b++){var c=a/2;this.f.push(a/360);this.g.push(a/(2*Math.PI));this.a.push(c);this.h.push(a);a*=2}};var tN=2*Math.PI;function uN(a){var b=Math.floor(a+1E-6);return 1E-6>a-b?b:a};function vN(a,b){this.origin=new Float64Array(3);a&&dG(this.origin,a);this.a=new Float64Array(3);b&&dG(this.a,b)}vN.prototype.set=function(a,b){dG(this.origin,a);dG(this.a,b)};function wN(a){function b(b,c){xN(a,b,c,f);return f.origin[0]-f.a[0]*f.origin[2]/f.a[2]}var c=a.c,d=a.a,e=Yn(yN(a)+1,0,d),f=new vN,g=b(0,e),h=b(0,d);e=b(c,e);c=b(c,d);return new rN(Math.min(g,h,e,c),Math.max(g,h,e,c))}function zN(a){var b=wN(a);a=Math.floor(b.start/tN+.5);b=Math.ceil(b.a/tN-.5);-5>a&&(a=-5);5<b&&(b=5);return new rN(a,b)}function AN(a){return a.a/2/Math.tan(a.g/2)/a.s*2*Math.PI} +function BN(a){var b=MJ();SJ(b,0,a.b,a.o);var c=a.a,d=c/2/Math.tan(a.g/2),e=MJ();e[0]=2/a.c*d;e[1]=0;e[2]=0;e[3]=0;e[4]=0;e[5]=2/c*-d;e[6]=0;e[7]=0;e[8]=0;e[9]=0;e[10]=-1;e[11]=-1;e[12]=0;e[13]=0;e[14]=2/3*2*d-d;e[15]=d;a=MJ();PJ(e,b,a);return a};function CN(a){this.j=null;this.i=new rN(0,0);this.a=new rN(0,0);this.l=a;this.f=2;this.h=this.g=this.c=this.b=0;this.o=new Float32Array(4);this.m=MJ()} +function DN(a,b,c,d,e,f){var g=a.j,h=a.c;if(0==a.f||1==a.f){g=1==a.f;var k=1/Math.pow(2,d);h=Math.pow(2,a.b-d);b=b*k+e;if(b+k<a.i.start/tN+.5||b>a.i.a/tN+.5)f=!1;else{b*=a.c;d=c*k*a.c;c=(g?Math.floor(b):b)-a.g;e=(g?Math.floor(d):d)-a.h;var l=k=h;g&&(g=Math.floor(d+256*h)-a.h,k=(Math.floor(b+256*h)-a.g-c)/256,l=(g-e)/256);NJ(f,k,l,1,c,e,0);f=!0}return f}k=1/(1<<d);d=h/256*k;f[0]=d;f[1]=0;f[2]=0;f[3]=0;f[4]=0;f[5]=d;f[6]=0;f[7]=0;f[8]=0;f[9]=0;f[10]=1;f[11]=0;f[12]=0;f[13]=0;f[14]=0;f[15]=1;c=c*k-(-g.i/ +tN+.5);f[12]=(b*k-(g.h/tN+.5)+e)*h;f[13]=c*h;a=a.m;SJ(a,0,g.b,g.o);PJ(a,f,f);f[12]+=g.c/2;f[13]+=g.a/2;return!0}function EN(a,b,c){var d=0!=c[4]||0!=c[1],e=Math.floor(c[0]+.5),f=Math.floor(c[5]+.5),g=1E-6<Math.abs(c[0]-e)||1E-6<Math.abs(c[5]-f),h=pF(2,a.l);a=c[12]*h;h*=c[13];if(d||g)return b.transform(c[0],c[1],c[4],c[5],a,h),1/Math.sqrt(c[0]*c[0]+c[1]*c[1]);b.transform(e,0,0,f,Math.floor(a+.5),Math.floor(h+.5));return 1/Math.sqrt(e*e)} +function sK(a,b,c,d,e,f){for(var g=a.o,h=MJ(),k=0,l=a.a.start;l<=a.a.a;l++)if(DN(a,b,c,d,l,h)){var m=h,n=g,p=e.b,q=WJ;q[0]=e.a;q[1]=p;q[2]=0;q[3]=1;RJ(m,WJ,n);f[2*k]=g[0];f[2*k+1]=g[1];k++}return k};var FN=1/512,kK=new bK;function GN(a,b,c){a=new oq(-256,a.width+256,a.height+256,-256);var d=Math.floor((a.right-a.left)/128),e=Math.floor((a.bottom-a.top)/128),f=d*e,g=HN(f);IN(b,a,d,e,g);a=[];JN(g,f,b,a);f={};for(g=0;g<a.length;g++)d=a[g],f[d]||(f[d]=jK(b[d]));d=[];for(g=0;g<a.length;g+=2){e=a[g];var h=a[g+1];KN(b[e],f[e],b[h],f[h],d,c)}kK.reset();d.sort(function(a,b){c&&a[0].uc==b[0].uc&&a[0].ab!=b[0].ab?b=a[0].ab?-1:1:(a=a[0],b=b[0],b=a.v-b.v||a.h-b.h);return b});return d} +function IN(a,b,c,d,e){for(var f,g,h,k,l=0;l<a.length;l++)if(g=a[l],2!=g.wb)for(f=g.o,g=LN(b.left,f.left,c),h=LN(b.left,f.right,c),k=LN(b.top,f.top,d),f=LN(b.top,f.bottom,d);k<=f;k++)for(var m=g;m<=h;m++)e[k*c+m].push(l)}function JN(a,b,c,d){for(var e,f,g,h,k,l,m=0;m<b;m++)for(var n=0;n<a[m].length-1;n++)for(var p=n+1;p<a[m].length;p++)e=a[m][n],f=c[e],g=a[m][p],h=c[g],k=f.o,l=h.o,k.top>l.bottom-FN||k.bottom<l.top+FN||k.left>l.right-FN||k.right<l.left+FN||(1!=f.wb||1!=h.wb)&&d.push(e,g)} +function KN(a,b,c,d,e,f){for(var g=0;g<b.length;g++)for(var h=0;h<d.length;h++){var k=b[g],l=d[h];if(!(k.b&&k.b===l.b||k.a[8]>l.a[10]||l.a[8]>k.a[10]||k.a[9]>l.a[11]||l.a[9]>k.a[11]||k.c&&!ZJ(k,l)||l.c&&!ZJ(l,k))){b=0>(a.v-c.v||a.h-c.h);f&&a.uc==c.uc&&a.ab!=c.ab&&(b=a.ab);1==a.wb&&(b=!0);1==c.wb&&(b=!1);b?e.push([a,c]):e.push([c,a]);return}}}function HN(a){for(var b=Array(a),c=0;c<a;c++)b[c]=[];return b}function LN(a,b,c){a=Math.floor((b-a)/128);return 0>a?0:a>=c?c-1:a};function MN(){this.g=[];this.h=!1;this.a=null;this.f=new WH(0,0);this.c=new WH(0,0);this.b=new WH(0,0)}MN.prototype.reset=function(a){this.f.x=0;this.f.y=0;this.b.x=0;this.b.y=0;this.c.x=0;this.c.y=0;this.a=NN(a);ON(this,a);this.h=!1};function NN(a){return{lat:PN(a),lng:QN(a),zoom:a.getZoom(),rotation:RN(a),ta:SN(a),width:TN(a),height:UN(a)}}function ON(a,b){if(a.a){var c=QN(b),d=PN(b);if(c!=a.b.x||d!=a.b.y)b=b.l,VN(b,a.a.lng,a.a.lat,a.f),VN(b,c,d,a.c),a.b.x=c,a.b.y=d}} +function WN(a){return a.c.x-a.f.x}function XN(a){return a.c.y-a.f.y}function YN(a){return a.data.g&&0!=a.a.j.length?a.a.Ga:!1}MN.prototype.getZoom=function(){return this.a?this.a.zoom:-1};function ZN(a,b,c,d,e,f,g){this.m=a;this.a=b;this.g=c;this.o=d;this.j=-1;this.f=null;this.l=-1;this.h=null;this.s=e;this.u=f;this.v=g;this.b=this.za=-1;this.i=this.c=!1}ZN.prototype.ka=function(){return this.o};function XM(a,b,c){a=0==b?a.f:a.h;return!a||c>=a.length?-1:a[c]};function $N(a,b,c,d){this.b=a;this.o=b;this.f=c;this.m=d;this.a=new MN;this.c=!1;this.g=-1;this.h=null;this.j=0}var aO=Math.tan(ao(60)/2); +function bO(a,b,c,d,e,f){var g=a.f,h=a.c^d&&0<g,k=h||a.g>e,l=!1;!d&&a.c&&(l=!0);a.c=d;if(!a.c||k){k=[];for(var m=[],n=[],p={},q=!1,t=0;t<b.length;++t){var v=b[t],u=c[t];p[v.N.aa()]||(p[v.N.aa()]=!0,v.data.g&&(k.push(v),m.push(u),v.a.Ga?q=q||v.a.s:n.push(v)),(v=v.b)&&!p[v.N.aa()]&&(p[v.N.aa()]=!0,v.data.g&&(k.push(v),m.push(u),v.a.Ga||n.push(v))))}b=q;c=a.a;p=Na(k,YN);if(p.length!=c.g.length)c.h=!0;else for(q=0;q<p.length;q++)p[q].N.aa()!=c.g[q].N.aa()&&(c.h=!0);c.g=p;if(!(h=h||b||l))a:if(h=a.a,l= +a.b,f=!!f,h.h||!h.a)h=!0;else if(b=NN(l),b.zoom!=h.a.zoom||b.rotation!=h.a.rotation||b.ta!=h.a.ta||b.width!=h.a.width||b.height!=h.a.height)h=!0;else{if(0<SN(l)||f)if(b.lat!=h.a.lat||b.lng!=h.a.lng){h=!0;break a}h=!1}if(h)n=a.h,a.h=a.b.ba(),n=a.m&&(!n||Ps(a.h,n)),a.a.reset(a.b),cO(a,k),dO(a,k,m,d,n,e),a.j++;else if(ON(a.a,a.b),0<n.length)for(cO(a,n),d=0;d<n.length;++d)for(m=n[d].a.j,f=0;f<m.length;f++)h=m[f],l=!h.s,h.b?(h.b.screenX+=WN(a.a),h.b.screenY+=XN(a.a),h.b.c&&(l=!1)):h.a&&h.a.o&&(l=!1),iK(h), +h.Gb(l,e,!0,a.f);for(n=0;n<k.length;++n)for(d=k[n],m=d.a.j,f=0;f<m.length;++f)h=m[f],gK(h,e,g)&&a.l(d,h)}}$N.prototype.l=sa; +function dO(a,b,c,d,e,f){for(var g=new fo(TN(a.b),UN(a.b)),h=[],k=[],l=g.height,m=0;m<b.length;++m){var n=a,p=b[m],q=c[m],t=l,v=f,u=h,w=k;if(p.a.Ra!=v){p.a.Ra=v;p=p.a.j;for(var y=0;y<p.length;++y){var A=p[y],z;if(!(z=A.B))if(A.b){z=t-q.top;var C=t-q.bottom;z=0<z&&A.b.screenY<z||C<t&&A.b.screenY>C}else z=!1;z||eO(A)?A.Gb(!1,v,!0,n.f):2==A.wb?w.push(A):u.push(A)}}}b=a.f;q=a.b.getZoom();c=0;m=[];for(l=0;l<h.length;++l)n=h[l],d||n.s||q<n.m-1E-4||q>n.K+1E-4||(n.b?n.b.c:n.a&&n.a.o)?(n=n.Gb(!1,f,!1,b),n> +c&&(c=n)):m.push(n);for(l=0;l<m.length;l++)iK(m[l]);for(l=0;l<k.length;l++)iK(k[l]);d=GN(g,m,e);for(l=0;l<m.length;l++)e=m[l],n=e.Gb(!0,f,0!=e.wb,b),n>c&&(c=n);for(l=0;l<d.length;l++)e=d[l],e[0].ab&&(n=e[1].Gb(!1,f,!1,b),n>c&&(c=n),e[1].G&&(n=e[1].G.Gb(!1,f,!1,b),n>c&&(c=n)));for(l=0;l<k.length;++l)n=k[l],n=n.Gb((!n.l||n.l.ab)&&!(n.b?n.b.c:n.a&&n.a.o),f,!0,b),n>c&&(c=n);k=c;0<k&&(f+=k,f>a.g&&(a.o(f),a.g=f))} +function eO(a){if(!a.a)return!1;for(var b=a.a,c=0;c<a.c.length;++c){var d=a.c[c];if(0>d.i||d.h>a.a.a-1)return!0;var e=Math.floor(d.i)+1;d=Math.ceil(d.h)-1;if(0<=d-e)for(;e<=d;++e){var f=b.i[e];if(f>aO||f<-aO)return!0}}return!1} +function cO(a,b){for(var c={},d=a.b.l,e=0;e<b.length;++e){var f=b[e],g=f.data,h=c[g.getZoom()];h||(h=fO(d,g.getZoom()),c[g.getZoom()]=h);var k=256*tK(g);g=256*uK(g);f=f.a.j;for(var l=0;l<f.length;++l){var m=f[l];if(m.b)a.i(m,h,k,g);else if(m.a){var n=m.a;n.o=h.gd(n.a,n.l,n.g,k,g,n.altitude);cL(n.c,n.a,n.g);n.m=0;n.j=null;n=m.c;for(var p=0;p<n.length;++p)n[p].A();xM(m)}}}}$N.prototype.i=function(a,b,c,d){if(a=a.b)UJ[0]=a.a,UJ[1]=a.b,a.c=b.gd(1,UJ,VJ,c,d,a.altitude),a.screenX=VJ[0],a.screenY=VJ[1]};function gO(a,b){$N.call(this,a,sa,0,b)}F(gO,$N);function hO(a){this.i=a;this.c=[];this.j=[];this.h=[];this.g=[];this.l=[];this.b=this.a=0;this.f=-1}function iO(a,b){var c=a.i.createTexture();a.c.push(c);a.a+=b;return a.c.length-1}function jO(a,b){a.j.push(b);a.a+=b.c}function kO(a,b,c){a.h.push(b);a.g.push(0);a.l.push(c);return a.h.length-1}function lO(a){a.f=$p(a.i.h,a,function(){a.f=-1;mO(a)},a.a,a.c.length);a.b=1} +function mO(a){if(1==a.b){a.b=2;-1!=a.f&&(Vp(a.i.h.a,a.f),a.f=-1);for(var b=0;b<a.c.length;++b)a.i.deleteTexture(a.c[b]);for(b=0;b<a.h.length;++b)a.l[b].call(a.h[b]);for(b=0;b<a.j.length;b++){for(var c=a.j[b],d=c.b,e=0;e<c.a.length;++e){var f=d.b.b[6*c.a[e].f+2],g=d.b;Kq(g,c.a[e].f);g.v--;0==--d.h[f]&&(d.a.deleteBuffer(d.g[f]),d.g[f]=null)}c.buffer=null;c.a.length=0}a.c=[];a.h=[];a.g=[];a.l=[];a.j=[]}};function nO(){Pp.call(this);this.b=this.m=this.h=this.g=0;this.la=1;this.Pa=this.s=!1;this.I=this.ja=this.G=this.L=this.Ba=this.ga=this.c=null;this.T=[];this.ha=[];this.U=[];this.W=[];this.P=[];this.S=[];this.Y=this.H=this.V=this.o=this.va=this.ya=this.C=null;this.j=[];this.v=[];this.Ga=!1;this.Ra=-1;this.A=this.u=null;this.Z=-1;this.Sa=!1;this.Ia=this.D=this.rc=null;this.K=-1;this.l=this.J=null;this.pa=this.ra=0;this.Ja=!1;this.Za=this.Wa=-1;this.Qa=!1;this.i=[];this.jb=this.f=this.fa=this.a=null; +this.ia=this.B=0;this.ib=-1;this.$a=this.Oa=!1;this.Ca=-1;this.La=0}F(nO,Pp);function oO(a){mO(a.a);a.a=null}nO.prototype.X=function(){for(;this.J&&"pending"==this.J.getState();)this.J.cancel();this.a&&oO(this);this.D&&(BM(this.D),this.D=null);this.fa&&(this.fa.$(),this.fa=null)};function pO(a,b){this.N=a;this.data=b;this.a=new nO;this.c=this.b=null;if(b){a=this.a;var c=tK(b),d=uK(b),e=b.getZoom(),f=1/Math.pow(2,e);a.g=c*f;a.h=d*f;a.m=e;a.b=f/256;a.Z=c%3+1+d%3*3+10*e;if(b=b.a.getExtension(96629873))a.la=nI(b),a.s=null==b.b?!1:b.b,a.Pa=null==b.b?!1:b.b}}function qO(a){return!a.data&&null!==a.c}function rO(a){var b=a.a.a;b&&1==b.b&&1==b.b&&Wp(b.i.h.a,b.f);a.b&&rO(a.b)}function sO(a,b){a=new pO(a,null);a.c=b;return a};function tO(){this.g=-1;this.b=!0;this.a=new uO(-1);this.h=this.f=this.i=this.j=this.c=0}var vO=[0,1,1],wO=5/255; +function xO(a,b,c,d,e,f){var g=d.zoom;d=0>a.a.zoom?0:g-a.a.zoom;var h=E();var k=c.length;var l=a.g;a.g=h;0>l?k=Infinity:(h-=l,0<d&&(a.c=0),0!=k||a.a.a.length?(d=a.c-h,0<=d?(a.c=d,h=0):(a.c=0,h=-d)):a.c=400,k=h);d=new uO(g);yO(d,c,e,f);if(f){g=c.length?c[0].N.getZoom():b.length?b[0].N.getZoom():g;h=[];for(l=0;l<b.length;l++)if(b[l].N.getZoom()==g){var m=sO(b[l].N,0);h.push(m)}yO(d,h,e,f)}e=d.zoom;f=Infinity;g=-Infinity;h=Infinity;l=-Infinity;for(m=0;m<b.length;m++){var n=b[m].N;if(n.getZoom()==e){var p= +iC(n);n=jC(n);p<f&&(f=p);n<h&&(h=n);p>g&&(g=p);n>l&&(l=n)}}for(m=0;m<c.length;m++)n=c[m].N,p=iC(n),n=jC(n),p<f&&(f=p),n<h&&(h=n),p>g&&(g=p),n>l&&(l=n);a.j=h;a.i=g;a.f=l;a.h=f;if(0<k)for(b=a.a,c=k,k=0;k<b.a.length;k++)zO(b.a[k],c);b=a.a;c=a.h;k=a.j;e=a.i;f=a.f;g=d.zoom-b.zoom;for(h=0;h<b.a.length;h++)if(l=b.a[h],l.a!=l.b||0!=l.a)if(0==g)p=l.x,n=l.y,p>=c&&p<=e&&n>=k&&n<=f&&AO(d,p,n,l);else if(0<g){var q=1<<g;p=l.x<<g;n=l.y<<g;m=p+q-1;q=n+q-1;if(!(m<c||q<k||p>e||n>f)){var t=Math.max(c,p);p=Math.max(k, +n);m=Math.min(e,m);q=Math.min(f,q);for(n=p;n<=q;n++)for(p=t;p<=m;p++)AO(d,p,n,l)}}else p=l.x>>-g,n=l.y>>-g,p<c||n<k||p>e||n>f||AO(d,p,n,l);a:{for(b=0;b<d.a.length;b++)if(c=d.a[b],c.a!=c.b){b=!1;break a}b=!0}a.b=b;a.a=d} +function yO(a,b,c,d){if(0!=b.length){for(var e=b[0].N.getZoom(),f=0;f<b.length;f++){var g=b[f],h=g.N,k=c?-1:g.c;g=0>k;if(g||d)var l=k=1;else 0>k?k=1:17<=k&&17<=e?k=0:(k=e-k,k=3<=k?vO[2]:2<=k?vO[1]+k%1*(vO[2]-vO[1]):1<=k?vO[0]+k%1*(vO[1]-vO[0]):0),l=0;BO(a,new CO(iC(h),jC(h),g,k,l))}a.zoom=e}}function AO(a,b,c,d){var e=(e=a.b[67108864*b+c])?a.a[e-1]:void 0;e||(e=new CO(b,c,!0,1,0),BO(a,e),e.b=0,e.c=!1);e.a=d.a}function zO(a,b){var c=a.b-a.a;a.a=Math.abs(c)<wO?a.b:a.a+c*(1-Math.exp(3*-b/80))} +function CO(a,b,c,d,e){this.x=a;this.y=b;this.c=c;this.a=e;this.b=d}function uO(a){this.b=[];this.a=[];this.zoom=a}function BO(a,b){var c=67108864*b.x+b.y,d=a.b[c];d||(a.a.push(b),d=a.a.length);a.b[c]=d};function DO(){this.j=this.l=0}var EO=0,FO=0,GO=0,HO=0;DO.prototype.u=function(a){this.l+=a.l;this.j+=a.j};DO.prototype.m=function(){var a=new DO;a.l=this.l;a.j=this.j;return a};function IO(a){this.g=a;this.b=this.c=0;this.a=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];this.f=0}function JO(a){a.c=0;for(var b=a.b=0;b<a.a.length;b++)a.a[b]=0;a.f=0}function KO(a,b){var c=a.b,d=a.a,e=a.f;b.m=a.c;b.l=c;for(a=b.a=0;a<d.length;a++)b.a+=d[a]*(a<LO.length?LO[a]:1);b.g=e} +function MO(a,b){for(var c=0;c<b.length;++c)for(var d=b[c].a,e=0;e<d.length;++e)for(var f=d[e].a,g=d[e].b,h=0;h<f.length;++h){var k=a,l=f[h],m=g.zoom;if(qO(l))0>l.c?k.f++:(k.b++,k.a[Yn(m-l.c,0,k.a.length-1)]++);else{var n=l.a;n.Oa&&(n.$a?(k.g.l++,0==n.La&&GO++):(k.g.j++,0==n.La&&HO++),n.La++);l.data&&l.N.getZoom()==m&&4!=l.N.Ea()&&k.c++}}};function NO(a,b,c,d){this.i=b;this.c=c;this.l=a;a=this.h=a.Pf;a.a=d;for(b=0;b<a.c.length;++b)OO(a)&&a.a.ic(a.c[b].Md,2,!0);this.j=d;this.b=[];this.a=[];this.f=[];this.g=-1}function PO(a){if(-1==a.g){for(var b=a.b,c=0,d=0;d<b.length;++d)for(var e=b[d].a,f=0;f<e.length;++f)for(var g=e[f].a,h=0;h<g.length;++h)qO(g[h])&&c++;a.g=c}return a.g};function QO(){this.height=this.width=this.ta=this.i=this.b=this.zoom=this.lng=this.lat=0;this.h=1;this.g=0;this.c=this.a=!1;this.f=1};function qH(){this.a=0;this.b=null}function RO(a,b){a.b=b}function SO(a){a.a++;a.b&&1==a.a&&a.b(1)};function TO(a){Qb.call(this,"DataEvent",a)}F(TO,Qb);function UO(a,b,c,d,e,f){Qb.call(this,"FrameComplete",a);this.startTime=b;this.h=c;this.g=d;this.f=e;this.c=f}F(UO,Qb);function VO(a,b){Qb.call(this,"FrameStart",a);this.startTime=b}F(VO,Qb);function WO(a,b,c){this.l=a;this.j=b;this.m=c}WO.prototype.u=function(a){this.l+=a.l;this.j+=a.j;this.m+=a.m};function XO(a,b){this.o=YO();this.b=null;this.j=a;this.i=b?b.j:null;this.c=-1;this.s=b?b.c:-1;this.h=-1;this.u=b?b.h:-1;this.v=b?b.f:-1;this.f=-1;this.g=this.a=this.l=this.m=0}var LO=[0,.1,.22,.5,.78,.9];function YO(){return x.performance&&x.performance.now?x.performance.now():E()} +function ZO(a){var b=a.b?a.b-a.o:YO()-a.o;if(a.i){var c=a.i;var d=a.j;c=!(c.h===d.h&&c.i===d.i&&c.m===d.m&&c.s===d.s&&c.j===d.j&&c.l===d.l&&c.f===d.f&&c.o===d.o&&c.b===d.b&&c.v===d.v&&c.g===d.g&&c.B===d.B&&c.A===d.A&&c.c===d.c&&c.a===d.a)}else c=1;c=c||a.c!=a.s||a.h!=a.u||a.f!=a.v?b:0;d=a.m+a.l+a.g;a=a.a+a.g;b*=0<d?a/d:0;return new WO(b,0<c?b:0,c)};function $O(){this.a=null;this.b=new WO(0,0,0)};var aP=WF();function bP(){this.height=this.width=this.b=this.ta=this.rotation=this.zoom=this.a=this.lng=this.lat=0}function cP(a,b){b=b||new bP;b.lat=a.lat;b.lng=a.lng;b.a=a.a;b.zoom=a.zoom;b.rotation=a.rotation;b.ta=a.ta;b.b=a.b;b.width=a.width;b.height=a.height;return b}function dP(a){var b=a.lat;90<b?a.lat=90:-90>b&&(a.lat=-90);b=a.lng;if(180<=b||-180>b)a.lng=Zn(b+180)-180;0>=a.zoom&&(a.zoom=0);b=a.rotation;if(360<=b||0>b)a.rotation=Zn(b);b=a.ta;0>b?a.ta=0:179.9<b&&(a.ta=179.9)};function eP(a,b,c){c=c||fP[0];vG(a.j,a.l,a.f,gP);var d=a.b,e=a.g,f=-a.o,g=gP;nG(c,-d);oG(c,0,0,-(g[2]+6371010));pG(c,-Math.PI/2);qG(c,-f);pG(c,g[1]);rG(c,-g[0]-Math.PI/2);a=a.c/a.a;f=fP[1];g=gP[2];var h=Math.abs(d)-e/2;g=h>=Math.PI/2?0:(g+6371010-6379856)*Math.cos(e/2)/Math.cos(h);h=2.5/Math.tan(e/2);g=g<h?.95*h:.95*g;var k=gP[2]+6371010;d=Math.tan(Math.abs(d)+Math.atan(Math.sqrt(a*a+1)/2/(1/(2*Math.tan(e/2)))));h=d*d+1;var l=-2*k;k=k*k-40451024652544;var m=l*l-4*h*k;0>=m||0>=d?d=(0<k?Math.sqrt(k): +0)+Math.sqrt(251537928192):(h=(-l-Math.sqrt(m))/(2*h),d*=h,d=Math.sqrt(h*h+d*d));h=e/2;e=d-g;l=Math.sin(h);0!=e&&0!=l&&0!=a&&(h=Math.cos(h)/l,f[0]=h/a,f[1]=0,f[2]=0,f[3]=0,f[4]=0,f[5]=h,f[6]=0,f[7]=0,f[8]=0,f[9]=0,f[10]=-(d+g)/e,f[11]=-1,f[12]=0,f[13]=0,f[14]=-(2*g*d)/e,f[15]=0);kG(f,c,b)}var gP=WF(),fP=[gG(),gG()];function hP(){this.a=WF()}var iP=eG(),jP=WF();function kP(a,b,c,d){ZF(b,a.a,iP);var e=aG(iP);a=-cG(iP,c);40589768420100>e||0>a?d&&$F(iP,6371010/Math.sqrt(e),d):($F(c,a,jP),YF(iP,jP,jP),e=aG(jP),40589768420100<=e?d&&$F(bG(jP,d),6371010,d):d&&($F(c,a-Math.sqrt(40589768420100-e),d),YF(b,d,d)))};function lP(a){this.a=a;this.b=!1}var mP=new WH(0,0),nP=WF(),oP=[eG(),eG(),eG(),eG(),eG()],pP=[gG(),gG(),gG()],qP=new vN;function fO(a,b){return a.b?new rP(a.a,b):new sP(a.a,b)}function VN(a,b,c,d){tG(b,c,0,nP);tP(a,d)} +function tP(a,b){var c=nP[0],d=nP[1];if(a.b){var e=new Float32Array(2),f=new Float32Array(2);a=fO(a,0);e[0]=128+128*c/Math.PI;e[1]=128-128*d/Math.PI;a.gd(1,e,f,0,0,0);b.x=f[0];b.y=f[1]}else{XF(nP,c,d,0);c=a.a;d=nP||WF();f=1/c.s;e=c.L;a=nP[1];var g=nP[2];e[0]=(nP[0]-c.h)*f;e[1]=(a-c.i)*f;e[2]=(g-c.m)*f;e[3]=1;iG(c.C,uP(c));f=c.C;a=e[0];g=e[1];var h=e[2],k=e[3];e[0]=a*f[0]+g*f[4]+h*f[8]+k*f[12];e[1]=a*f[1]+g*f[5]+h*f[9]+k*f[13];e[2]=a*f[2]+g*f[6]+h*f[10]+k*f[14];e[3]=a*f[3]+g*f[7]+h*f[11]+k*f[15];f= +1/e[3];e[0]*=f;e[1]*=f;e[2]*=f;vP(c,e,d);b.x=nP[0];b.y=nP[1]}}function sP(a,b){var c=gG(),d=pP[0],e=tN/(1<<b)/256;hG(c,e,-e,e);e=1/a.s;var f=a.C;f[0]=e;f[1]=0;f[2]=0;f[3]=0;f[4]=0;f[5]=e;f[6]=0;f[7]=0;f[8]=0;f[9]=0;f[10]=e;f[11]=0;f[12]=0;f[13]=0;f[14]=0;f[15]=1;oG(f,-a.h,-a.i,-a.m);kG(f,c,c);iG(d,uP(a));kG(d,c,c);iG(d,wP(a));kG(d,c,c);d=WF();yG(a.h,0,0,b,d);a=256*d[0];b=256<<b;this.a=a-b/2;this.b=a+b/2;this.f=b;this.c=c} +sP.prototype.gd=function(a,b,c,d,e,f){for(var g=this.a,h=this.b,k=this.f,l=this.c,m=0;m<a;m++){var n=b[2*m]+d,p=b[2*m+1]+e;n>h?n-=k:n<g&&(n+=k);var q=l[0]*n+l[4]*p+l[8]*f+l[12],t=l[1]*n+l[5]*p+l[9]*f+l[13];n=l[3]*n+l[7]*p+l[11]*f+l[15];.01>n&&(n=.01);c[2*m]=q/n;c[2*m+1]=t/n}return!1};function rP(a,b){var c=gG();this.c=c;b=tN/(1<<b)/256;hG(c,b,-b,b);b=pP[0];c=pP[1];eP(a,b,c);this.b=gG();var d=pP[2];iG(d,wP(a));kG(d,b,this.b);a=pP[2];lG(c,a);this.a=WF();sG(a,this.a)} +rP.prototype.gd=function(a,b,c,d,e,f){for(var g=oP[1],h=oP[2],k=oP[3],l=oP[4],m=this.c,n=this.b,p=!1,q=0;q<a;q++){h[0]=b[2*q]+d;h[1]=b[2*q+1]+e;h[2]=f;mG(m,h,g);var t=2*Math.atan(Math.exp(g[1]))-Math.PI/2;xG(g[0],t,6371010*g[2]*Math.cos(t),k);if(!p){t=this.a;var v=t[0]-k[0],u=t[1]-k[1],w=t[2]-k[2];t=cG(t,t)-40589768420100<v*v+u*u+w*w;p=p||t}mG(n,k,l);c[2*q]=l[0];c[2*q+1]=l[1]}return p};function xP(a,b,c,d,e,f,g,h,k){rc.call(this);this.L=a;this.a=b;this.canvas=h;this.Ba=c;this.gc=e;this.C=g;this.f=new NO(c,a,b,d);this.c=new QO;this.i=0;this.V=k;this.Ja=new $O;this.Ka=new DO;this.v=new IO(this.Ka);this.ya=this.I=0;this.P=!0;this.ha=-1;yP(this);var l=this;zP(this.Ba,function(a){l.P=!0;!a&&0<l.L.a||l.Wb()})}F(xP,rc);r=xP.prototype; +r.wc=function(){if(this.Qd()){this.a.f=this.canvas.c;this.vc();var a=this.Ja,b=new XO(this.a.a,a.a);a.a&&(a.a.b=YO(),a.b.u(ZO(a.a)));a.a=b;this.cd(b);this.dispatchEvent(new UO(this,this.i,E(),this.f.a.length,this.ya,PO(this.f)));b.c=this.C.j;b.h=this.Xa();b.f=0}};function yP(a){var b=a.L,c=a.gc;RO(b,function(a){1!=a||0<b.a||uo(c);2!=a||uo(c)})}r.Qd=function(){this.i=E();this.dispatchEvent(new VO(this,this.i));return!0}; +r.vc=function(){if(!this.rd()){this.P=!1;this.ha=this.a.s();var a=this.f;a.b=a.l.getData(a.c.a,a.c.f,a.c.ba(),a.c.c,a.a,a.c.g,a.j,0<a.i.a);var b=a.h.getData(a.c.a);a.b=a.b.concat(b);a.a=[];a.f=[];b=a.b;for(var c=a.a,d=a.f,e=0;e<b.length;e++)for(var f=b[e].a,g=0;g<f.length;g++)for(var h=f[g].b,k=f[g].a,l=0;l<k.length;l++){var m=k[l];m.data&&!UM(m.data)&&-1==c.indexOf(m)&&(c.push(m),d.push(h))}a.g=-1;this.dispatchEvent(new TO(this,this.f.a))}a=0<this.L.a;a=!(0<PO(this.f))||!a;d=yN(this.a.a)+1;this.Td(); +b=this.c;c=this.a;b.lat=PN(c);b.lng=QN(c);b.zoom=c.getZoom();b.b=Math.floor(b.zoom+1E-6);b.width=TN(c);b.height=UN(c);b.f=c.f;b.g=Yn(d,0,b.height);b.h=wG(b.lat);d=RN(c);b.i=d;b.ta=-ao(SN(c));b.a=!1;b.c=a};r.Xa=function(){return this.a.f};r.cd=function(){};r.rd=function(){return!AP(this)};function AP(a){return a.P||a.ha<a.a.s()}r.Td=function(){bO(this.C,this.f.a,this.f.f,!this.a.h,this.i)};r.Wb=function(){uo(this.gc)};function BP(){this.b=this.a=this.i=this.c=this.g=this.f=0}function CP(a){return a.b/a.g}BP.prototype.u=function(a){this.f+=a.f;this.g+=a.g;this.c+=a.c;this.i+=a.i;this.a+=a.a;this.b+=a.b};function DP(){FM.call(this);this.b=1}F(DP,FM);DP.prototype.cancel=function(){this.b--;return this.b?!1:DP.R.cancel.call(this)};function EP(a,b){this.h=a;this.g=b;this.b=new BP;this.a=[];this.c=[];this.f=[]}function FP(a,b){return a.a.K-b.a.K}function GP(a,b,c){if(UM(b.data))return a=new FM,HM(a,b),a;if(-1==b.a.K){var d=new DP;d.wait(D(a.j,a,b));b.a.J=d;b.a.K=c;-1!=a.f.indexOf(b)?(Ta(a.f,b),a.c.push(b)):(a.a.unshift(b),a.a.sort(FP),HP(a));a.b.f++}else b.a.J.b++,c>b.a.K&&(b.a.K=c,a.a.sort(FP),HP(a));return b.a.J} +EP.prototype.start=function(){if(!this.a.length)return Dr;var a=this.a.pop(),b=a.a.J,c=x.performance&&x.performance.now?x.performance.now():E(),d=this.h.Od(a),e=x.performance&&x.performance.now?x.performance.now():E();this.b.b+=e-c;"success"==d.getState()?this.h.Ub(a)?HM(b,a):this.a.push(a):"error"==d.getState()?KM(b):(this.c.push(a),d.wait(D(this.i,this,a)));return HP(this)}; +EP.prototype.i=function(a){-1!=this.c.indexOf(a)?(Ta(this.c,a),this.a.push(a),this.a.sort(FP),HP(this)):-1!=this.f.indexOf(a)&&Ta(this.f,a)};EP.prototype.j=function(a){var b=a.a.J;JM(b)?(-1!=this.a.indexOf(a)?Ta(this.a,a):-1!=this.c.indexOf(a)&&(Ta(this.c,a),this.f.push(a)),this.b.i++):"error"==b.getState()?this.b.c++:this.b.g++;a.a.K=-1;a.a.J=null};function HP(a){if(!a.a.length)return Dr;var b=a.a[a.a.length-1].a.K;a.g.Mb(a,b);a.g.qd(a,b);return a.start};function IP(a,b){this.g=1;this.c=a;this.a=go("DIV");this.a.className="canvas-container";this.a.style.position="absolute";this.a.style.left="0px";this.a.style.top="0px";this.a.style.zIndex=0;this.c.appendChild(this.a);this.j=a.clientWidth;this.i=a.clientHeight;this.h=new Float64Array(2);this.l=new Float64Array(2);this.m=new sN;this.b=new Float64Array(2);this.s=uN(b.zoom);this.o=this.c.style.backgroundColor;this.f=null;JP(this,b,this.h);KP(this)} +function KP(a){var b="translate3d("+-a.b[0]+"px, "+-a.b[1]+"px, 0) scale(1)";a.a.style.transform=b;a.a.style.webkitTransform=b}function JP(a,b,c){var d=a.m,e=b.lat,f=uN(b.zoom);if(f==Math.floor(f)&&f<d.a.length){var g=d.a[f];var h=d.f[f];f=d.g[f]}else f=256*Math.pow(2,f),g=f/2,h=f/360,f/=2*Math.PI;d.b=g+b.lng*h;b=Yn(Math.sin(ao(e)),-.9999,.9999);d.c=g-.5*Math.log((1+b)/(1-b))*f;d=a.m.c-a.i/2;c[0]=Math.round((a.m.b-a.j/2)*a.g)/a.g;c[1]=Math.round(d*a.g)/a.g} +function LP(a,b){var c=!1;if(a.j!=b.width||a.i!=b.height){c=b.width;var d=b.height;if(c!=a.j||d!=a.i)a.j=c,a.i=d,a.c.style.width=c+"px",a.c.style.height=d+"px";c=!0}c||a.s!=uN(b.zoom)?(a.s=uN(b.zoom),JP(a,b,a.h),b=a.l,c=a.h,b[0]=c[0],b[1]=c[1],b=a.b,b[0]=0,b[1]=0):(JP(a,b,a.l),b=a.l,c=a.h,d=a.b,d[0]=b[0]-c[0],d[1]=b[1]-c[1]);KP(a)};function MP(a,b,c){this.bottom=a;this.top=b;this.zoom=c};function NP(a,b,c,d,e,f,g,h){var k=Math.floor(256*Yn(h.la,1,2))/256;this.h=new CN(k);xP.call(this,a,b,d,this,g,h,new gO(b,!0),f,c);this.b=e;this.Ra=new iL(k);this.La=new QH;this.Qa=new qJ;this.Sa=new yM(k,"arial,sans-serif");this.Da=new oK(this.h);this.Ia=new $K(this.Da);this.J=this.m=null;this.B=new tO;this.Pa=h.u;this.Ca=h.T;this.Oa=h.G;this.Ga=this.ra=this.va=this.pa=this.ja=null;this.H=!1;this.U=0;this.G=k;this.M={};this.j=!1;this.l=this.g=this.D=null;this.W={};this.ia=-1;this.K=!1;this.Y=!0; +this.Z=!1;this.ga=this.fa=-1;this.T=!1;this.A=1;this.S=h.Z;this.s=null;OP(this,h)}F(NP,xP);var PP=1/Math.pow(2,19);r=NP.prototype;r.wc=function(){this.canvas.c=(this.D||this.canvas).c;NP.R.wc.call(this)}; +function OP(a,b){function c(a,b){var c=a[3];return[c*a[0]+(1-c)*b[0],c*a[1]+(1-c)*b[1],c*a[2]+(1-c)*b[2],c+(1-c)*b[3]]}var d=a.Ba.oc;a.m=new eN(a,a.Sa,a.Da,a.G,d,b);a.J=new EP(a.m,a.gc.b);MA(d.b,function(){a.dd()},a);a.ja=new oJ(PH(aI),PH(bI),PH(cI),a.G);a.pa=new oJ(PH(c(aI,YH)),PH(c(bI,YH)),PH(c(cI,YH)),a.G);a.va=new oJ(PH(dI),PH(eI),PH(fI),a.G);a.ra=new oJ(PH(c(dI,XH)),PH(c(eI,XH)),PH(c(fI,XH)),a.G);a.Ga=new iI;QP(a.a,D(a.dd,a))}r.dd=function(a){a?(this.U=this.i,this.H=!1):this.H=!0;uo(this.gc)}; +r.getContext=function(){return this.b};r.Vd=function(){return this.i<this.I||AP(this)||this.c.a||this.i<=this.U||!this.B.b?!1:!0};function RP(a){var b=gI(a.a.i,a.a.c);a.M[b]||(a.M[b]=PH(hI(a.a.i,a.a.c)));return a.M[b]} +r.cd=function(a){var b=this.h,c=this.a.a,d=this.Xa();b.l=d;var e=AN(c);b.j=c;b.i=wN(c);b.a=zN(c);b.b=Math.log(e/256)/Math.LN2;b.c=e;b.f=2;0==c.o&&0==c.b&&0==c.v&&(1E-9>Math.abs(b.b-Math.round(b.b))?(b.f=0,b.b=Math.round(b.b)):(b.f=1,b.b=uN(b.b)),b.c=256*Math.pow(2,b.b),e=(.5-c.i/tN)*b.c-c.a/2,b.g=Math.round(((c.h/tN+.5)*b.c-c.c/2)*d)/d,b.h=Math.round(e*d)/d);this.K=1E-4<Math.abs(this.a.getZoom()-this.ia);a:if(b=SP(this),c=this.f.a,this.j){d=!this.B.b;if(!this.A){e=TP(this,c);var f=!!PO(this.f);if(e|| +f||d||!this.Y)this.A=3}e=this.Xa()!=this.fa;f=this.h;f=f.a.a-f.a.start+1;var g=UP(c),h=g||this.Z;if(0!=this.ga||this.K||b||e||1<f||h||this.T)this.A=1;if(this.A){--this.A;if(0==this.A){this.W=[];VP(this,c);this.ia=this.a.getZoom();this.fa=this.Xa();this.ga=0;this.Z=g;this.Y=!d;this.T=!1;b=!0;break a}this.H=!0}b=!1}else b=!0;try{this.b.setTransform(1,0,0,1,0,0)}catch(t){c=Error(),c.message="initContext_: Error accessing canvas.",nF(c)}if(b){b=this.f.a;bO(this.C,b,this.f.f,!this.a.h,this.i);JO(this.v); +this.j&&(c=this.l,d=RP(this),c.g=this.Xa(),d!=c.o&&(c.c.style.backgroundColor=d,c.o=d),LP(this.l,this.c));this.U=0;this.S||oF(this.b,!1);this.l&&this.b.clearRect(0,0,this.b.canvas.width,this.b.canvas.height);this.b.save();c=WP(this);d=pF(2,this.Xa());this.b.translate(-c.x*d,-c.y*d);c=this.f.b;this.b.save();this.b.scale(d,d);h=this.a;d=this.b;f=h.a;e=f.c;f=f.a;g=hI(h.i,h.c);var k=h.l,l=267.1960013541594/Math.PI;h=new WH(0,0);VN(k,-180,l,h);var m=new WH(0,0);VN(k,180,l,m);var n=new WH(0,0);VN(k,-180, +-l,n);var p=new WH(0,0);VN(k,180,-l,p);k=1>Math.abs(h.x-m.x);l=1>Math.abs(h.y-m.y);if(!k&&h.x>m.x||k&&h.x>n.x){var q=h;h=n;n=q;q=m;m=p;p=q}l?(jI(d,g,0,0,e,h.y),jI(d,g,0,n.y,e,f)):k?(jI(d,g,0,0,h.x,f),jI(d,g,n.x,0,e,f)):(kI(d,g,h,m,e,f,0),kI(d,g,n,p,e,f,f));this.b.restore();MO(this.v,c);for(d=0;d<c.length;++d)c[d].a.length&&(e=c[d].a[0],0<e.a.length&&XP(this,e.a,d));this.S||oF(this.b,!0);if(!this.c.a&&this.a.h){c=[];for(d=0;d<b.length;d++)e=b[d],YP(e),(UM(e.data)||this.m.Ub(e)||e.a.s)&&c.push(e);0< +c.length&&(b=this.C,aL(this.Ia,this.b,c,this.Xa(),WN(b.a),XN(b.a)))}this.b.restore();this.j&&(b=this.l,c=WP(this),b.f&&(c="translate("+(b.b[0]+c.x)+"px, "+(b.b[1]+c.y)+"px) scale(1)",b.f.style.transform=c,b.f.style.webkitTransform=c))}else LP(this.l,this.c);this.H&&this.dd(!0);a&&KO(this.v,a)};r.fb=function(a){return UM(a.data)?!0:this.m.Ub(a)};r.ic=function(a,b,c){return c&&TM(this.m,a)?$M():GP(this.J,a,b)};r.wd=function(){return this.J.b}; +function XP(a,b,c){for(var d=[],e=[],f=[],g=0;g<b.length;++g){var h=b[g];h.data||null===h.c?h.data&&(a.c.a?h.N.getZoom()==a.c.b&&(h=sO(h.N,-1),e.push(h)):(d.push(h),4!=h.N.Ea()&&f.push(h))):e.push(h)}b=gI(a.a.i,a.a.c);g=a.Pa&&a.Oa||a.Ca;if(2===b){var k=a.va;var l=a.ra}else 1===b&&(k=a.ja,l=a.pa);if(g&&k&&l)b=new MP(0,a.c.height,a.c.b),xO(a.B,f,e,b,a.c.a,a.Ca),!a.B.b&&a.dd(),ZP(a,f,e,k,l,!0),a.c.a||$P(a,d,c),ZP(a,f,e,k,l,!1);else{if(!g&&l)for(f=l,k=a.Xa(),l=MJ(),b=0;b<e.length;b++){g=e[b].N;h=a.h.a.a; +for(var m=a.h.a.start;m<=h;m++)DN(a.h,iC(g),jC(g),g.getZoom(),m,l)&&(a.b.save(),EN(a.h,a.b,l),pJ(f,a.b,k),a.b.restore())}a.c.a||$P(a,d,c)}} +function $P(a,b,c){if(b.length){b.sort(aQ||Za);var d=pF(2,a.Xa()),e=a.b,f=!1;if(0<c&&b[0].N.getZoom()!=a.c.b){f=!0;e=null;if(!a.s)e=go("canvas");else if(a.s.canvas.width<a.b.canvas.width||a.s.canvas.height<a.b.canvas.height)e=a.s.canvas;e&&(e.width=a.b.canvas.width,e.height=a.b.canvas.height,a.s=e.getContext("2d"),a.S||oF(a.s,!1));e=a.s;e.setTransform(1,0,0,1,0,0);e.clearRect(0,0,a.b.canvas.width,a.b.canvas.height);c=WP(a);e.translate(-c.x*d,-c.y*d)}c=MJ();for(var g=0;g<b.length;g++){var h=b[g],k= +h.data;if(!UM(k)){bQ(a.V,h);h.a.s||UM(h.data)||a.m.Ub(h)||4!=h.N.Ea()||GP(a.J,h,2);var l=h.a.f;if(h.a.Sa||l.i.length){h.a.Sa=!1;l=a.m;var m=h,n=m.a;n.rc=null;n.D&&(BM(n.D),n.D=null);n.Ia=null;oN(l,m);qN(l,m,!0)}l=a.h.a.a;for(m=a.h.a.start;m<=l;m++)if(DN(a.h,tK(k),uK(k),k.getZoom(),m,c)){e.save();var p=EN(a.h,e,c);f&&e.clearRect(0,0,256*d,256*d);if(h.a.s||4==h.N.Ea()){e.save();e.beginPath();e.rect(0,0,256*d,256*d);e.clip();e.scale(d,d);n=oN(a.m,h);p<PP&&(p=PP);var q=e,t=a.a.getZoom();kJ(n);lJ(n,q, +p,t,-1);e.restore()}else q=a,t=h,n=e,(p=t.a.Ia)?(q=pF(2,q.Xa()),n.drawImage(p,0,0,256*q,256*q)):(p=t.a.D)&&AM(p,n,q.Xa());e.restore()}}}f&&(a.b.save(),a.b.setTransform(1,0,0,1,0,0),a.b.drawImage(e.canvas,0,0,a.b.canvas.width,a.b.canvas.height,0,0,a.b.canvas.width,a.b.canvas.height),a.b.restore())}}function YP(a){a=a.a;if(a.j.length)for(var b=a.f.j,c=0;c<b.length;++c)for(var d=b[c],e=0;e<a.v.length;++e)for(var f=a.v[e].a,g=0;g<f.length;++g){var h=f[g];h.a==d&&h&&h.c&&h.c.i()}} +function ZP(a,b,c,d,e,f){if(c.length||b.length){b=a.B.a.a;c=a.B.a.zoom;for(var g=a.Xa(),h=MJ(),k=0;k<b.length;k++){var l=b[k];if(0<l.a&&l.c==f){a.b.globalAlpha=l.a;for(var m=a.h.a.a,n=a.h.a.start;n<=m;n++)DN(a.h,l.x,l.y,c,n,h)&&(a.b.save(),EN(a.h,a.b,h),l.c?pJ(e,a.b,g):pJ(d,a.b,g),a.b.restore())}}a.b.globalAlpha=1}}r.Je=function(){return!1};r.Xa=function(){return Math.floor(256*this.a.f)/256};r.vc=function(){NP.R.vc.call(this);this.c.f=this.Xa()};r.Td=function(){var a=this.C;ON(a.a,a.b)}; +function SP(a){var b=!1;if(a.j){var c=a.D.a,d=a.canvas.a,e=c.width/parseInt(c.style.width,10),f=function(a){return 256*(Math.floor(a/256)+2)};f=a.K?sr:f;a=f(parseInt(c.style.width,10));c=f(parseInt(c.style.height,10));if(d.style.width!=a+"px"||d.style.height!=c+"px")d.style.width=a+"px",d.style.height=c+"px";a=a*e|0;e=c*e|0;if(d.width!=a||d.height!=e)d.width=a,d.height=e,b=!0}return b} +r.X=function(){if(this.j){this.j=!1;this.l=null;var a=this.g;a&&a.parentNode&&a.parentNode.removeChild(a);this.g=null;this.canvas=this.D;a=this.canvas.a;this.b=a.getContext("2d");a.style.display=""}NP.R.X.call(this)};function TP(a,b){for(var c=0;c<b.length;c++){var d=!(!b[c].data||!a.fb(b[c])&&!b[c].a.s);if(!a.W[b[c].N.aa()]==d)return!0}return!1}function UP(a){for(var b=0;b<a.length;b++)if(a[b].a.s)return!0;return!1} +function VP(a,b){for(var c=0;c<b.length;c++){var d=b[c];a.W[d.N.aa()]=a.fb(d)||d.a.s}} +function WP(a){if(a.K||!a.j)return new WH(0,0);var b=WF(),c=a.a.l;if(c.b){c=c.a;var d=pP[1];eP(c,pP[0],d);var e=pP[2];lG(d,e);var f=WF(),g=WF();sG(e,f);var h=c.a/2,k=c.c/2,l=Math.tan(c.g/2);d=WF();d[0]=(0-k)/k*l*(k/h);d[1]=(0-h)/h*-l;d[2]=-1;mG(e,d,g);ZF(g,f,g);bG(g,g);e=new vN(f,g);kP(new hP,e.origin,e.a,d);mP.x=Math.atan2(d[1],d[0]);mP.y=Math.atan2(d[2],Math.sqrt(d[0]*d[0]+d[1]*d[1]));c=Math.atan2(c.j,c.l);mP.x<c-Math.PI&&(mP.x+=2*Math.PI);mP.x>c+Math.PI&&(mP.x-=2*Math.PI);tG(180*mP.x/Math.PI,180* +mP.y/Math.PI,0,b)}else xN(c.a,0,0,qP),c=-qP.origin[2]/qP.a[2],b[0]=qP.origin[0]+qP.a[0]*c,b[1]=qP.origin[1]+qP.a[1]*c,b[2]=0;c=WF();e=Math.ceil(a.c.zoom-1E-6);yG(b[0],b[1],b[2],e,c);b=new WH(0,0);a=a.a.l;zG(Math.floor(c[0]),Math.floor(c[1]),e,nP);tP(a,b);b.x|=0;b.y|=0;return b}function aQ(a,b){return a.N||b.N?a.N?b.N?a.N.getZoom()-b.N.getZoom():1:-1:0};function cQ(a){this.a=a}cQ.prototype.m=function(){var a=this.a,b=new BP;b.f=a.f;b.g=a.g;b.c=a.c;b.i=a.i;b.a=a.a;b.b=a.b;return b};function dQ(a,b,c,d,e){Pp.call(this);this.a=d;this.b=b;this.i=e}F(dQ,Pp);dQ.prototype.wc=function(){this.a.wc()};dQ.prototype.g=function(){return this.a};dQ.prototype.f=function(){return new cQ(new BP)};dQ.prototype.h=sa;function eQ(a,b,c,d,e,f,g){dQ.call(this,a,b,c,d,e,f,g);this.c=d}F(eQ,dQ);eQ.prototype.g=function(){return this.c};eQ.prototype.f=function(){return new cQ(this.c.wd())};eQ.prototype.X=function(){this.c.$();eQ.R.X.call(this)}; +eQ.prototype.h=function(){eQ.R.h.call(this);var a=this.c;a.j=!0;a.D=a.canvas;var b=a.D.a;b.style.display="none";a.canvas=new io;SP(a);var c=a.canvas.a;b.parentNode&&b.parentNode.insertBefore(c,b.nextSibling);a.b=c.getContext("2d");a.g=go("DIV");a.g.className="canvas-renderer";a.g.style.overflow="hidden";a.g.style.position="absolute";a.g.style.width=b.width+"px";a.g.style.height=b.height+"px";a.g.style.backgroundColor=RP(a);a.g.style.direction="ltr";a.g.style.webkitUserSelect="none";a.g.style.b="none"; +a.g.style.a="none";b.parentNode.insertBefore(a.g,b);c.style.backgroundColor="rgba(0,0,0,0)";c.style.position="absolute";c.style.zIndex=100;a.l=new IP(a.g,a.c);b=a.l;b.f=c;b.a.appendChild(b.f);a.T=!0};function rH(){this.D=MJ();this.J=MJ();this.M=MJ();this.K=MJ();this.u=WF();this.L=eG();this.P=WF();this.O=XF(WF(),1,1,1);this.C=gG();this.H=!0;this.m=this.i=this.h=0;this.s=1;this.v=this.b=this.o=this.f=this.l=this.j=0;this.g=.4363323129985824;this.B=1/3;this.A=Number.MAX_VALUE;this.G=this.a=this.c=1;this.I=[]} +function fQ(a,b){var c=!1,d=!1,e=!1,f=!1,g=!1;B(b.g)&&(b.g!=a.h&&(g=!0,a.h=b.g),c=!0);B(b.h)&&(b.h!=a.i&&(g=!0,a.i=b.h),c=!0);B(b.i)&&(b.i!=a.m&&(g=!0,a.m=b.i),c=!0);B(b.f)&&(b.f!=a.s&&(g=!0,a.s=b.f),d=!0);B(b.j)&&(b.j!=a.j&&(g=!0,a.j=b.j),e=!0);B(b.l)&&(b.l!=a.l&&(g=!0,a.l=b.l),e=!0);B(b.m)&&(b.m!=a.f&&(g=!0,a.f=b.m),e=!0);B(b.c)&&(b.c!=a.o&&(g=!0,a.o=b.c),f=!0);B(b.ta)&&(b.ta!=a.b&&(g=!0,a.b=b.ta),f=!0);B(b.b)&&(b.b!=a.v&&(g=!0,a.v=b.b),f=!0);B(b.a)&&b.a!=a.g&&(g=!0,a.g=b.a);B(b.s)&&b.s!=a.B&&(g= +!0,a.B=b.s);B(b.o)&&b.o!=a.A&&(g=!0,a.A=b.o);B(b.width)&&b.width!=a.c&&(g=!0,a.c=b.width);B(b.height)&&b.height!=a.a&&(g=!0,a.a=b.height);g&&(!f||c||e||(e=!0),!d&&e&&c&&(b=a.j-a.h,d=a.l-a.i,f=a.f-a.m,a.s=Math.sqrt(b*b+d*d+f*f)),e&&!c&&gQ(a),c&&!e&&hQ(a),a.H=!0,a.G++,iQ(a))}function jQ(a,b){b=b||new SF;b.g=a.h;b.h=a.i;b.i=a.m;b.f=a.s;b.j=a.j;b.l=a.l;b.m=a.f;b.c=a.o;b.ta=a.b;b.b=a.v;b.a=a.g;b.s=a.B;b.o=a.A;b.width=a.c;b.height=a.a;return b}function AH(a,b){a.I.push(b)} +function iQ(a){for(var b=0;b<a.I.length;b++)a.I[b]()}function uP(a){kQ(a);return a.D}function wP(a){var b=a.M,c=a.u,d=a.L;vP(a,a.P,c);vP(a,a.O,d);ZF(d,c,d);NJ(b,d[0],d[1],d[2],c[0],c[1],c[2]);return b} +function kQ(a){if(a.H){var b=a.D,c=a.c/a.a,d=a.B,e=a.A,f=a.g/2,g=e-d,h=Math.sin(f);0!=g&&0!=h&&0!=c&&(f=Math.cos(f)/h,b[0]=f/c,b[1]=0,b[2]=0,b[3]=0,b[4]=0,b[5]=f,b[6]=0,b[7]=0,b[8]=0,b[9]=0,b[10]=-(e+d)/g,b[11]=-1,b[12]=0,b[13]=0,b[14]=-(2*d*e)/g,b[15]=0);SJ(a.K,-a.v,-a.b,-a.o);PJ(a.D,a.K,a.D);e=1/a.s;b=a.D;c=e*(a.h-a.j);d=e*(a.i-a.l);e*=a.m-a.f;b[12]+=b[0]*c+b[4]*d+b[8]*e;b[13]+=b[1]*c+b[5]*d+b[9]*e;b[14]+=b[2]*c+b[6]*d+b[10]*e;b[15]+=b[3]*c+b[7]*d+b[11]*e;QJ(a.D,a.J);a.H=!1}} +function xN(a,b,c,d){d=d||new vN;var e=a.u,f=a.B,g=a.A;e[0]=b;e[1]=c;e[2]=g/(g-f);b=e||WF();c=e[1];var h=e[2];b[0]=2*e[0]/a.c-1;b[1]=2*-c/a.a+1;b[2]=2*h-1;e[2]=(g+f)/(g-f);f=a.C;kQ(a);iG(f,a.J);f=a.C;g=d.a;b=e[0];c=e[1];e=e[2];g[0]=b*f[0]+c*f[4]+e*f[8]+f[12];g[1]=b*f[1]+c*f[5]+e*f[9]+f[13];g[2]=b*f[2]+c*f[6]+e*f[10]+f[14];bG(d.a,d.a);XF(d.origin,a.j,a.l,a.f)}function vP(a,b,c){c=c||WF();var d=b[1],e=b[2];c[0]=.5*(b[0]+1)*a.c;c[1]=.5*(-d+1)*a.a;c[2]=.5*(e+1)} +function gQ(a){lQ(a,a.u);a.h=a.j+a.u[0];a.i=a.l+a.u[1];a.m=a.f+a.u[2]}function hQ(a){lQ(a,a.u);a.j=a.h-a.u[0];a.l=a.i-a.u[1];a.f=a.m-a.u[2]}function mQ(a,b,c){var d=1/Math.tan(a.g/2),e=a.a,f=B(c)?c:a.b;a=2/e*(B(c)?a.s*Math.cos(c)+a.m:a.f)*d;b=d*Math.cos(f)-(1-2*b/e)*Math.sin(f);return 0>b?Infinity:a/(b*b)}function yN(a){return(1-1/Math.tan(a.g/2)/Math.tan(a.b))*a.a/2} +function lQ(a,b){XF(b,0,0,-a.s);var c=a.C,d=a.o,e=a.b,f=a.v,g=Math.cos(d);d=Math.sin(d);var h=Math.cos(e);e=Math.sin(e);var k=Math.cos(f);f=Math.sin(f);c[0]=g*k-h*d*f;c[1]=h*g*f+k*d;c[2]=f*e;c[3]=0;c[4]=-g*f-k*h*d;c[5]=g*h*k-d*f;c[6]=k*e;c[7]=0;c[8]=e*d;c[9]=-g*e;c[10]=h;c[11]=0;c[12]=0;c[13]=0;c[14]=0;c[15]=1;a=a.C;c=b[0];g=b[1];f=b[2];b[0]=c*a[0]+g*a[4]+f*a[8];b[1]=c*a[1]+g*a[5]+f*a[9];b[2]=c*a[2]+g*a[6]+f*a[10]};function sH(a,b,c){this.a=a;this.l=new lP(a);new sN;this.b=new bP;this.f=1;this.D=new oq(0,0,0,0);this.H=0;this.A=[];this.i=[0];this.c=[0];this.B=new Os;this.v=this.u=0;this.m=this.o=this.h=!0;this.G=-1;this.j=new SF;this.I=c||null;this.C=0;this.J=b;this.g=!1;var d=this;AH(this.a,function(){tH(d)})}sH.prototype.s=function(){return this.H};function QP(a,b){a.A.push(b)}function tH(a){a.H++;for(var b=0;b<a.A.length;b++)a.A[b].call(null)}sH.prototype.ba=function(){return this.B}; +function vH(a,b){nQ(a);return cP(a.b,b)}function wH(a,b){dP(b);a.b=cP(b,a.b);b=a.b;var c=a.j;c.j=void 0;c.l=void 0;c.m=void 0;c.s=void 0;c.o=void 0;c.c=-ao(b.rotation);c.ta=ao(b.ta);c.b=0;c.a=ao(b.b);c.width=b.width;c.height=b.height;c.f=1/Math.tan(c.a/2)*c.height/2*(tN/256/Math.pow(2,b.zoom));tG(b.lng,b.lat,b.a,aP);c.g=aP[0];c.h=aP[1];c.i=aP[2];fQ(a.a,a.j)} +function nQ(a){if(a.G!=a.a.G){jQ(a.a,a.j);0!=a.j.b&&(a.j.b=0,fQ(a.a,a.j));var b=a.j,c=a.b;c.rotation=-(180*b.c/Math.PI);c.ta=180*b.ta/Math.PI;c.b=180*b.a/Math.PI;c.width=b.width;c.height=b.height;uG(b.g,b.h,b.i,aP);c.lng=aP[0];c.lat=aP[1];c.a=aP[2];c.zoom=Math.log(1/Math.tan(b.a/2)*(b.height/2)/b.f*tN/256)/Math.LN2;dP(a.b);a.I?(b=a.I,c=a.a,b=a.g?oQ(c):pQ(b.a,c,a.f)):b=a.b.zoom;1E-6<=Math.abs(b-a.C)&&(a.C=b);a.G=a.a.G}}function UN(a){nQ(a);return a.b.height}function TN(a){nQ(a);return a.b.width} +function PN(a){nQ(a);return a.b.lat}function QN(a){nQ(a);return a.b.lng}sH.prototype.getZoom=function(){nQ(this);return this.C};function RN(a){nQ(a);return a.b.rotation}function SN(a){nQ(a);return a.b.ta}sH.prototype.ud=function(){nQ(this);return this.b.a};function uH(a,b){a.g!=b&&a.J&&(a.g=b,a.l.b=b,tH(a))};function xH(a){this.b=a;this.a={}} +function bQ(a,b){var c=b.a.f,d=0,e=c.l;if(0!=e){for(var f=Object.keys(c.h),g=f.length-1;0<=g;--g){var h=f[g];if(!a.a[h]){var k=c,l=h,m=k.h[l];if(m){for(var n=0;n<m.length;++n)for(var p=m[n],q=k.g[p],t=0;t<q.length;++t)if(q[t].key==l)if(t==q.length-1)k.f[p]=!0,q.length=t;else{q.splice(t,1);break}delete k.h[l]}}}f=b.N.ba();for(h in a.a)if(h>e&&(d++,m=a.a[h],l=m.b.dg(b.data,f)))for(g=c,k=h,m=m.a,g.h[k]=l,n=0;n<l.length;++n)p=l[n],(q=g.g[p])?q.push({key:k,modifier:m}):g.g[p]=[{key:k,modifier:m}],g.f[p]= +!0}a=a.b;c.l=0;c.j.length=0;c.i.length=0;b=Object.keys(c.f);if(b.length){for(d=0;d<b.length;++d)h=parseInt(b[d],10),c.o[h]?c.j.push(h):c.i.push(h),(e=c.g[h])&&e.length?(f=a.G(c.a[h],c.s,e[e.length-1].modifier),e=c,f!=e.a[h]?(void 0===e.b[h]&&e.c++,e.b[h]=f):void 0!==e.b[h]&&(delete e.b[h],e.c--)):void 0!==c.b[h]&&(c.c--,delete c.b[h]);c.f={}}};function yH(a){this.b=a;this.a=a.b}yH.prototype.G=function(a,b,c){a=RA(PB(this.b,b),a);var d=c.apply(a);if($z(d))c=0;else{c=this.a;a=pr(c.h,"localStyle!"+ ++c.g);b=new zA;if(d){var e=b.style;e.c=d.c;e.D=d.D;e.l=d.l;e.s=d.s;e.j=d.j;e.C=d.C;e.m=d.m?Va(d.m):null;e.o=d.o;e.v=AA(d.v);e.A=AA(d.A);e.u=AA(d.u);e.f=d.f;e.a=d.a;e.g=d.g;e.h=d.h;e.i=d.i;e.b=new Uint8Array(840);d=d.b;e=e.b;for(var f=0;840>f;f++)e[f]=d[f]}b=b.style;a>c.b&&(c.b=a);c.f[a]=b;c.a&&c.a.call(c.c,a,b);c=a}return c};function qQ(a,b,c,d,e,f,g){this.c=a;this.a=b;this.b=c;this.priority=d;this.type=e;this.g=f;this.f=g;this.h=null}function rQ(a,b){return new qQ(b,a.a,a.b,a.priority,a.type,a.g,a.f)}qQ.prototype.mb=function(){if(!this.h){for(var a=this.c.length,b=Array(a),c=0;c<a;++c)b[c]=new dC(this.c[c],this.b,this.a);this.h=b}return this.h};function sQ(){this.c=B(void 0)?void 0:2;this.b=B(void 0)?void 0:3}sQ.prototype.a=function(a,b,c,d,e,f){for(var g=[],h=0;h<d.length;++h){for(var k=[],l=tQ(e,a,b,f).a,m=0;m<l.length;++m)k.push.apply(k,l[m].a);k.length&&g.push(new qQ(k,c,d[h],this.c,this.b,!1,!1))}return g};function uQ(){}uQ.prototype.Xc=function(a,b,c,d){return b.Xc(new sQ,c,d)};function vQ(){}F(vQ,uQ);vQ.prototype.a=function(a,b,c,d,e,f,g,h,k){b=new NP(d,e,h,f,b.b,c,k,a);c=this.Xc(a,f,b,d);return new eQ(d,e,f,b,c,g,a.b)};function wQ(){}wQ.prototype.a=function(){return new vQ};NG(4,new wQ);function xQ(){this.a=0;this.b=2;this.c=0;this.j=this.g=this.h=this.f=this.i=null}function yQ(a,b,c){a.f=b;a.h=c||null}xQ.prototype.cancel=function(){if(3==this.a)return!1;var a=!1;this.f&&(a=this.f.call(this.h))&&(this.a=3);return a};xQ.prototype.start=function(a){if(0!=this.a)throw Error("Trying to reuse an Rpc object. Status is not INACTIVE");this.a=1;this.i=a};xQ.prototype.done=function(){};function zQ(a,b){if(0==b)throw Error("Trying to set the Rpc status to INACTIVE.");a.a=b} +function AQ(a,b){a.b=b;a.g&&a.g.call(a.j)}function BQ(a){var b=new xQ;b.b=a.b;return b};function CQ(a,b){this.b=a;this.c=b}CQ.prototype.a=function(a,b,c,d){d=d||new xQ;a=new DQ(a,b,c?c:null,d,this.b,this.c);DG(this.b,a,d.b)};function DQ(a,b,c,d,e,f){this.s=a;this.l=b;this.o=c;this.c=d;this.f=!1;this.a=null;this.g=e;this.m=f;this.h=!1;this.b=null;yQ(this.c,this.i,this);a=this.c;a.g=this.j;a.j=this||null} +DQ.prototype.start=function(a){this.a=BQ(this.c);this.a.start(this.c.i+".RequestSchedulerChannel");zQ(this.a,1);var b=this;this.m.a(this.s,function(a){b.h=!0;b.l(a);++b.c.c},function(){var c=b.o;b.a.done();zQ(b.c,b.a.a);c&&c();a()},this.a)};DQ.prototype.cancel=function(){return!this.a||this.h&&!this.f?!1:this.a.cancel()};DQ.prototype.i=function(){this.f=!0;return EG(this.g,this)};DQ.prototype.j=function(){DG(this.g,this,this.c.b)};function EQ(a){a=(new mB(a)).toString();this.b=a+=-1==a.indexOf("?")?"?":"&"}EQ.prototype.a=function(a){if(0==a.length)return this.b.slice(0,this.b.length-1);if("?"==a[0]||"&"==a[0])a=a.slice(1);return this.b+a};function FQ(a,b){this.f=pa(a)||a instanceof mB?new EQ(a):a;this.c=b;this.b=!1}function GQ(a,b,c,d){function e(a){nc(c);3!=d.a&&a&&b()}dc(c,"success",function(){e(!0)});dc(c,"abort",function(){e(!1)});dc(c,"error",function(){zQ(d,2);e(!0)});dc(c,"timeout",function(){zQ(d,2);e(!0)});dc(c,"readystatechange",function(){var b=c.$c();AD(c)&&4==yD(c)&&a(b)})} +FQ.prototype.a=function(a,b,c,d){d=d||new xQ;c=c||sa;var e=new mD;e.l=this.b;B(this.c)&&(e.f=this.c);yQ(d,function(){e.abort();return!0});GQ(b,c,e,d);a=this.f.a(a);rD(e,a)};var HQ=[];function IQ(a,b,c){this.b=a;this.f=b;this.g=c;this.a={};this.c={};for(a=0;a<HQ.length;++a)JQ(this,HQ[a].$f,HQ[a].result)}function JQ(a,b,c){"success"==c.getState()?KQ(a,b,c.na()):(a.a[b]=c,c.wait(function(){KQ(a,b,c.na());delete a.a[b]}))}function LQ(a){var b=new Sn;b.data[0]=68;var c=new Un(De(b,1));c.data[0]="set";c.data[1]=a;return new Js([b])} +function KQ(a,b,c){var d=PB(a.g,LQ(b)),e=new Mu;c=gd(c);yv(e,c);hd(c);d.a=e;if(null!=d.a.b)for(e=d.a.b,c=0;c<e.length;++c)d.g[e[c].wa()]=c;e=d.i;c=d.a;if(!e.c){if(null!=c.c||null!=c.j){Iv(c);c=c.c;for(var f=0;f<c.length;f++){var g=c[f],h=null==g.a?0:g.a;g=0>h;h=Math.abs(h);var k=h>>>0;h=Math.floor((h-k)/4294967296);h>>>=0;g&&(h=~h>>>0,k=(~k>>>0)+1,4294967295<k&&(k=0,h++,4294967295<h&&(h=0)));Ic=k;Jc=h;g=Lc(Ic,Jc);e.a.push(g);k=c[f];e.b[null==k.b?0:k.b]=g}}e.c=!0}TA(d,d.i.a);a.c[b]=!0} +function MQ(a,b,c){if(a.c[b])return $M();var d=a.a[b];if(d)return d;var e=new FM;a.a[b]=e;var f=MF(a.b,b);d=new xQ;AQ(d,c);c=NQ(a.f,f,a.b.M);var g=a.b.o();c.a("",D(function(a){g();KQ(this,b,a);HM(e,!0);delete this.a[b]},a),void 0,d);return e}function NQ(a,b,c){b=new FQ(b,"arraybuffer");b.b=c;return new CQ(a,b)};function OQ(){this.b=[];this.f=[];this.c=[];this.a=[[],[],[],[],[],[],[]]}function PQ(a){return a.b.length+a.c.length}function QQ(a,b){b=a.b[b];return a.a[b.a].indexOf(b)}OQ.prototype.G=function(a){return a<this.b.length?this.b[a].s:this.f[a-this.b.length]};function RQ(a,b,c,d,e,f,g,h){b=new ZN(b,c,e,a.b.length,f,g,h);a.b.push(b);return a.a[c][d]=b}function SQ(a,b,c){a.c.push(b);a.f.push(c);return PQ(a)-1};var TQ=null; +function UQ(a,b,c){var d=new Uint32Array(b*c);TQ||(TQ=new Uint32Array(4));var e=TQ,f=b/4;c/=4;for(var g=0;g<c;g++)for(var h=0;h<f;h++){var k=0+4*(g*f+h),l=a[k],m=l>>11,n=l>>5&63,p=l&31;m=m<<3|m>>2;n=n<<2|n>>4;p=p<<3|p>>2;e[0]=m|n<<8|p<<16|-16777216;var q=a[k+1],t=q>>11,v=q>>5&63,u=q&31;t=t<<3|t>>2;v=v<<2|v>>4;u=u<<3|u>>2;e[1]=t|v<<8|u<<16|-16777216;l<=q?(e[2]=m+t>>1|n+v>>1<<8|p+u>>1<<16|-16777216,e[3]=0):(e[2]=5*m+3*t>>3|5*n+3*v>>3<<8|5*p+3*u>>3<<16|-16777216,e[3]=3*m+5*t>>3|3*n+5*v>>3<<8|3*p+5*u>> +3<<16|-16777216);l=a[k+2];m=4*g*b+4*h;d[m+0]=e[l&3];d[m+1]=e[l>>2&3];d[m+2]=e[l>>4&3];d[m+3]=e[l>>6&3];m+=b;d[m+0]=e[l>>8&3];d[m+1]=e[l>>10&3];d[m+2]=e[l>>12&3];d[m+3]=e[l>>14];l=a[k+3];m+=b;d[m+0]=e[l&3];d[m+1]=e[l>>2&3];d[m+2]=e[l>>4&3];d[m+3]=e[l>>6&3];m+=b;d[m+0]=e[l>>8&3];d[m+1]=e[l>>10&3];d[m+2]=e[l>>12&3];d[m+3]=e[l>>14]}return d};function VQ(a,b,c,d){this.data=a;this.width=b;this.height=c;this.format=d||1};function WQ(){}function XQ(a,b){if(b.Db())if(b=b.Yb(),1==b.format){var c=b.width,d=b.height;b=b.data;Uo(jq(a,3553),b,c,d,6408,5121,0)}else 4==b.format?(c=b.width,d=b.height,b=b.data,Uo(jq(a,3553),b,c,d,6406,5121,0)):2==b.format?a.compressedTexImage2D(3553,0,33776,b.width,b.height,0,b.data):3==b.format&&a.compressedTexImage2D(3553,0,33779,b.width,b.height,0,b.data);else b.bc()&&(b=b.Ab(),Qo(jq(a,3553),b,6408,5121,0))};function YQ(a,b){b=B(b)?b:0;var c=B(void 0)?void 0:a.byteLength-b;this.a=new Uint8Array(a,b,c);new Int8Array(a,b,c)}function ZQ(a,b){return a.a[b]+(a.a[b+1]<<8)+(a.a[b+2]<<16)+16777216*a.a[b+3]};function $Q(){this.g=!1;this.b=this.a=null;this.f=!1;this.c=null;var a=x.URL;a&&a.createObjectURL&&a.revokeObjectURL?(this.a=D(a.createObjectURL,a),this.b=D(a.revokeObjectURL,a)):(a=x.webkitURL)&&a.createObjectURL&&a.revokeObjectURL&&(this.a=D(a.createObjectURL,a),this.b=D(a.revokeObjectURL,a));if(this.a&&this.b){try{100==(new x.Blob([new Uint8Array(100)])).size&&(this.g=!0)}catch(b){}this.g||(this.f=!0,x.ArrayBuffer&&x.ArrayBuffer.prototype.slice?x.BlobBuilder?this.c=x.BlobBuilder:x.WebKitBlobBuilder? +this.c=x.WebKitBlobBuilder:x.a?this.c=x.a:this.f=!1:this.f=!1)}}function aR(a){var b=2*(a[0]<<23)+(a[1]<<16)+(a[2]<<8)+a[3];switch(b){case 2303741511:var c="image/png";break;case 4292411360:c="image/jpeg";break;case 1195984440:c="image/gif";break;case 1145328416:c="image/x-dds";break;case 1380533830:c="image/unknown";12<a.length&&(b=2*(a[8]<<23)+(a[9]<<16)+(a[10]<<8)+a[11],1464156752==b&&(c="image/webp"));break;default:c="image/unknown"}return c};/* + + Copyright 2012 Mozilla Foundation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +function bR(){this.b=this.i=0;this.h=!1;this.buffer=null}function cR(a,b){var c=a.buffer,d=c?c.byteLength:0;if(b<d)return c;for(var e=512;e<b;)e<<=1;b=new Uint8Array(e);if(c)for(e=0;e<d;++e)b[e]=c[e];return a.buffer=b}function dR(a){for(var b,c=a.i;!a.h;)eR(a);b=a.b;b||(a.buffer=new Uint8Array(0));a.i=b;return a.buffer.subarray(c,b)}bR.prototype.reset=function(){this.i=0};function fR(a){this.g=null;this.c=this.f=this.a=0;a&&gR(this,a);bR.call(this)}F(fR,bR); +function gR(a,b){var c=0;c++;c++;a.g=b;a.a=c;a.f=0;a.c=0;a.i=0;a.b=0;a.h=!1}function hR(a,b){this.a=a;this.b=b} +var iR=new Uint32Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),jR=new Uint8Array(iR.length),kR=new Uint8Array(320),lR=new Uint32Array(512),mR=new Uint32Array(512),nR=new Uint32Array(512),oR=new Uint32Array([3,4,5,6,7,8,9,10,65547,65549,65551,65553,131091,131095,131099,131103,196643,196651,196659,196667,262211,262227,262243,262259,327811,327843,327875,327907,258,258,258]),pR=new Uint32Array([1,2,3,4,65541,65543,131081,131085,196625,196633,262177,262193,327745,327777,393345,393409,459009, +459137,524801,525057,590849,591361,657409,658433,724993,727041,794625,798721,868353,876545]),qR=new hR(new Uint32Array([459008,524368,524304,524568,459024,524400,524336,590016,459016,524384,524320,589984,524288,524416,524352,590048,459012,524376,524312,589968,459028,524408,524344,590032,459020,524392,524328,59E4,524296,524424,524360,590064,459010,524372,524308,524572,459026,524404,524340,590024,459018,524388,524324,589992,524292,524420,524356,590056,459014,524380,524316,589976,459030,524412,524348, +590040,459022,524396,524332,590008,524300,524428,524364,590072,459009,524370,524306,524570,459025,524402,524338,590020,459017,524386,524322,589988,524290,524418,524354,590052,459013,524378,524314,589972,459029,524410,524346,590036,459021,524394,524330,590004,524298,524426,524362,590068,459011,524374,524310,524574,459027,524406,524342,590028,459019,524390,524326,589996,524294,524422,524358,590060,459015,524382,524318,589980,459031,524414,524350,590044,459023,524398,524334,590012,524302,524430,524366, +590076,459008,524369,524305,524569,459024,524401,524337,590018,459016,524385,524321,589986,524289,524417,524353,590050,459012,524377,524313,589970,459028,524409,524345,590034,459020,524393,524329,590002,524297,524425,524361,590066,459010,524373,524309,524573,459026,524405,524341,590026,459018,524389,524325,589994,524293,524421,524357,590058,459014,524381,524317,589978,459030,524413,524349,590042,459022,524397,524333,590010,524301,524429,524365,590074,459009,524371,524307,524571,459025,524403,524339, +590022,459017,524387,524323,589990,524291,524419,524355,590054,459013,524379,524315,589974,459029,524411,524347,590038,459021,524395,524331,590006,524299,524427,524363,590070,459011,524375,524311,524575,459027,524407,524343,590030,459019,524391,524327,589998,524295,524423,524359,590062,459015,524383,524319,589982,459031,524415,524351,590046,459023,524399,524335,590014,524303,524431,524367,590078,459008,524368,524304,524568,459024,524400,524336,590017,459016,524384,524320,589985,524288,524416,524352, +590049,459012,524376,524312,589969,459028,524408,524344,590033,459020,524392,524328,590001,524296,524424,524360,590065,459010,524372,524308,524572,459026,524404,524340,590025,459018,524388,524324,589993,524292,524420,524356,590057,459014,524380,524316,589977,459030,524412,524348,590041,459022,524396,524332,590009,524300,524428,524364,590073,459009,524370,524306,524570,459025,524402,524338,590021,459017,524386,524322,589989,524290,524418,524354,590053,459013,524378,524314,589973,459029,524410,524346, +590037,459021,524394,524330,590005,524298,524426,524362,590069,459011,524374,524310,524574,459027,524406,524342,590029,459019,524390,524326,589997,524294,524422,524358,590061,459015,524382,524318,589981,459031,524414,524350,590045,459023,524398,524334,590013,524302,524430,524366,590077,459008,524369,524305,524569,459024,524401,524337,590019,459016,524385,524321,589987,524289,524417,524353,590051,459012,524377,524313,589971,459028,524409,524345,590035,459020,524393,524329,590003,524297,524425,524361, +590067,459010,524373,524309,524573,459026,524405,524341,590027,459018,524389,524325,589995,524293,524421,524357,590059,459014,524381,524317,589979,459030,524413,524349,590043,459022,524397,524333,590011,524301,524429,524365,590075,459009,524371,524307,524571,459025,524403,524339,590023,459017,524387,524323,589991,524291,524419,524355,590055,459013,524379,524315,589975,459029,524411,524347,590039,459021,524395,524331,590007,524299,524427,524363,590071,459011,524375,524311,524575,459027,524407,524343, +590031,459019,524391,524327,589999,524295,524423,524359,590063,459015,524383,524319,589983,459031,524415,524351,590047,459023,524399,524335,590015,524303,524431,524367,590079]),9),rR=new hR(new Uint32Array([327680,327696,327688,327704,327684,327700,327692,327708,327682,327698,327690,327706,327686,327702,327694,0,327681,327697,327689,327705,327685,327701,327693,327709,327683,327699,327691,327707,327687,327703,327695,0]),5); +function sR(a,b){for(var c=a.f,d=a.c,e=a.g,f=a.a,g;c<b;)g=e[f++],d|=g<<c,c+=8;a.c=d>>b;a.f=c-b;a.a=f;return d&(1<<b)-1}function tR(a,b){var c=b.a,d=b.b;b=a.f;for(var e=a.c,f=a.g,g=a.a;b<d;){var h=f[g++];e|=h<<b;b+=8}c=c[e&(1<<d)-1];d=c>>16;a.c=e>>d;a.f=b-d;a.a=g;return c&65535} +function uR(a,b,c,d){for(var e=0,f=b;f<c;++f)a[f]>e&&(e=a[f]);var g=1<<e;d=g<=d.length?d:new Uint32Array(g);for(var h=1,k=0,l=2;h<=e;++h,k<<=1,l<<=1)for(var m=b;m<c;++m)if(a[m]==h){var n=0,p=k;for(f=0;f<h;++f)n=n<<1|p&1,p>>=1;for(f=n;f<g;f+=l)d[f]=h<<16|m-b;++k}return new hR(d,e)} +function eR(a){var b=sR(a,3);b&1&&(a.h=!0);b>>=1;if(0==b){b=a.g;var c=a.a,d,e=d=b[c++];d=b[c++];e|=d<<8;c++;c++;a.c=0;a.f=0;d=a.b;var f=cR(a,d+e);e=d+e;a.b=e;for(var g=d;g<e;++g){if("undefined"==typeof(d=b[c++])){a.h=!0;break}f[g]=d}a.a=c}else{c=qR;d=rR;if(1!=b&&2==b){f=sR(a,5)+257;e=sR(a,5)+1;b=sR(a,4)+4;for(c=0;c<jR.length;++c)jR[c]=0;for(c=0;c<b;++c)jR[iR[c]]=sR(a,3);d=uR(jR,0,jR.length,lR);c=b=0;for(e=f+e;c<e;){g=tR(a,d);if(16==g){var h=2,k=3;g=b}else if(17==g)k=h=3,g=b=0;else if(18==g)h=7,k= +11,g=b=0;else{kR[c++]=b=g;continue}for(h=sR(a,h)+k;0<h--;)kR[c++]=g}c=uR(kR,0,f,mR);d=uR(kR,f,e,nR)}e=(f=a.buffer)?f.length:0;for(g=a.b;;)if(h=tR(a,c),256>h)g+1>=e&&(f=cR(a,g+1),e=f.length),f[g++]=h;else{if(256==h){a.b=g;break}h-=257;h=oR[h];k=h>>16;0<k&&(k=sR(a,k));b=(h&65535)+k;h=tR(a,d);h=pR[h];k=h>>16;0<k&&(k=sR(a,k));h=(h&65535)+k;g+b>=e&&(f=cR(a,g+b),e=f.length);for(k=0;k<b;++k,++g)f[g]=f[g-h]}}};/* + + MIT LICENSE + Copyright (c) 2011 Devon Govett + + 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 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. +*/ +function vR(){this.v=new fR;this.data=new Uint8Array(0);this.a=8;this.g=[];this.o=null;this.b={};this.h=null;this.text={};this.j=this.s=0;this.m=null;this.c=this.l=this.f=this.height=this.width=0;this.i=!1;this.u=0} +function wR(a){for(var b=null;;){var c=xR(a),d=a,e=String.fromCharCode(d.data[d.a++]);e+=String.fromCharCode(d.data[d.a++]);e+=String.fromCharCode(d.data[d.a++]);e+=String.fromCharCode(d.data[d.a++]);switch(e){case "IHDR":c=a;c.width=xR(c);c.height=xR(c);c.l=c.data[c.a++];c.c=c.data[c.a++];c.a++;c.a++;c.a++;break;case "acTL":c=a;c.h={hg:xR(c),ig:xR(c)||Infinity,frames:[]};break;case "PLTE":d=a;d.s=d.a;d.j=c;d.a+=c;break;case "fcTL":b&&a.h.frames.push(b);b=a;b.a+=4;c={width:xR(b),height:xR(b),mg:xR(b), +ng:xR(b)};d=yR(b);e=yR(b)||100;c.bg=1E3*d/e;c.cg=b.data[b.a++];c.Yf=b.data[b.a++];c.ag=[];b=c;break;case "fdAT":a.a+=4,c-=4;case "IDAT":d=a;if(b){e=b.data;for(var f=0;f<c;f++)e.push(d.data[d.a++])}else d.g.push(d.a),d.g.push(c),d.a+=c;break;case "tRNS":d=a;d.b={};switch(d.c){case 3:e=c;255>e&&(e=255);d.b.yd=Array(e);for(f=0;f<c;f++)d.b.yd[f]=d.data[d.a++];for(f=c;f<e;f++)d.b.yd[f]=255;break;case 0:d.b.gg=zR(d,c)[0];break;case 2:d.b.kg=zR(d,c)}break;case "tEXt":d=a;c=zR(d,c);e=c.indexOf(0);f=String.fromCharCode.apply(String, +c.slice(0,e));d.text[f]=String.fromCharCode.apply(String,c.slice(e+1));break;case "IEND":b&&a.h.frames.push(b);b=void 0;switch(a.c){case 0:case 3:case 4:a.f=1;break;case 2:case 6:a.f=3}a.i=4===(b=a.c)||6===b;a.u=a.l*(a.f+(a.i?1:0));b=a.g;if(2==b.length)d=new Uint8Array(a.data.buffer.slice(a.data.byteOffset+b[0],a.data.byteOffset+b[0]+b[1]));else{d=0;for(c=1;c<b.length;c+=2)d+=b[c];d=new Uint8Array(d);e=0;f=a.data;for(c=0;c<b.length;c+=2)for(var g=b[c],h=b[c+1],k=0;k<h;k++)d[e++]=f[g+k]}a.o=d;a.g= +[];return;default:a.a+=c}a.a+=4;if(a.a>a.data.length)throw Error("Incomplete or corrupt PNG file");}}function zR(a,b){for(var c=Array(b),d=0;d<b;d++)c[d]=a.data[a.a++];return c}function xR(a){var b=a.data[a.a++]<<24;var c=a.data[a.a++]<<16;var d=a.data[a.a++]<<8;a=a.data[a.a++];return b|c|d|a}function yR(a){var b=a.data[a.a++]<<8;a=a.data[a.a++];return b|a} +function AR(a){var b=null,c,d,e,f,g,h,k,l,m,n;null==b&&(b=a.o);if(0===b.length)return new Uint8Array(0);gR(a.v,b);var p=a.v;p=dR(p);b=a.u/8;var q=b*a.width;var t=new Uint8Array(q*a.height);var v=p.length;for(c=e=f=0;e<v;){switch(p[e++]){case 0:for(h=0;h<q;h+=1)t[c++]=p[e++];break;case 1:for(d=k=0;k<q;d=k+=1){a=p[e++];var u=d<b?0:t[c-b];t[c++]=(a+u)%256}break;case 2:for(d=l=0;l<q;d=l+=1){a=p[e++];var w=(d-d%b)/b;var y=f&&t[(f-1)*q+w*b+d%b];t[c++]=(y+a)%256}break;case 3:for(d=m=0;m<q;d=m+=1)a=p[e++], +w=(d-d%b)/b,u=d<b?0:t[c-b],y=f&&t[(f-1)*q+w*b+d%b],t[c++]=(a+Math.floor((u+y)/2))%256;break;case 4:for(d=n=0;n<q;d=n+=1){a=p[e++];w=(d-d%b)/b;u=d<b?0:t[c-b];0===f?y=g=0:(y=t[(f-1)*q+w*b+d%b],g=w&&t[(f-1)*q+(w-1)*b+d%b]);var A=u+y-g;w=Math.abs(A-u);d=Math.abs(A-y);A=Math.abs(A-g);u=w<=d&&w<=A?u:d<=A?y:g;t[c++]=(a+u)%256}break;default:throw Error("Invalid filter algorithm: "+p[e-1]);}f++}return t} +function BR(a){var b=a.s,c=a.data,d=a.b.yd||null;a=a.j;for(var e=new Uint8Array(a/3*4),f=0,g=0,h=0;h<a;h+=3)e[f++]=c[b+h],e[f++]=c[b+h+1],e[f++]=c[b+h+2],e[f++]=d?d[g++]:255;return e} +function CR(a,b,c){var d=a.f;var e=null;var f=a.i;a.j&&(e=a.m=a.m||BR(a),d=4,f=!0);a=b.length;if(1===d)if(e)if(f)for(f=d=0;d<a;d+=4,f++){var g=4*c[f];var h=e[g];b[d]=h;b[d+1]=h;b[d+2]=h;b[d+3]=e[g+1]}else for(f=d=0;d<a;d+=4,f++)g=4*c[f],h=e[g],b[d]=h,b[d+1]=h,b[d+2]=h,b[d+3]=255;else if(f)for(f=d=0;d<a;d+=4,f+=2)h=c[f],b[d]=h,b[d+1]=h,b[d+2]=h,b[d+3]=c[f+1];else for(f=d=0;d<a;d+=4,f++)h=c[f],b[d]=h,b[d+1]=h,b[d+2]=h,b[d+3]=255;else if(e)if(f)for(f=d=0;d<a;d+=4,f++)g=4*c[f],b[d]=e[g],b[d+1]=e[g+1], +b[d+2]=e[g+2],b[d+3]=e[g+3];else for(f=d=0;d<a;d+=4,f++)g=4*c[f],b[d]=e[g],b[d+1]=e[g+1],b[d+2]=e[g+2],b[d+3]=255;else if(f)for(d=0;d<a;d+=4)b[d]=c[d],b[d+1]=c[d+1],b[d+2]=c[d+2],b[d+3]=c[d+3];else for(f=d=0;d<a;d+=4,f+=3)b[d]=c[f],b[d+1]=c[f+1],b[d+2]=c[f+2],b[d+3]=255};var DR=null;function ER(a,b){if(!a.Db()){var c=a.b,d=new YQ(c.buffer,c.byteOffset+4),e=ZQ(d,0)+4;var f=ZQ(d,8);var g=ZQ(d,12),h=ZQ(d,76);d=ZQ(d,80);h&4&&(827611204==d||894720068==d)?b?(b=new Uint16Array(c.buffer,c.byteOffset+e,c.byteLength-e>>1),b=UQ(b,g,f),f=new VQ(new Uint8Array(b.buffer),g,f,1)):(b=new Uint8Array(c.buffer,c.byteOffset+e,c.byteLength-e),f=new VQ(b,g,f,827611204==d?2:3)):f=null;a.a=f;a.b=null;a.c=null;a.ld()}} +function FR(a,b){this.b=a;this.g=!0;this.c=b;this.mimeType=aR(a);this.f=this.bb=this.a=null}F(FR,WQ);r=FR.prototype;r.Ab=function(){return this.bb};r.Yb=function(){return this.a};r.Yd=function(){return this.a?this.a.width:this.bb?this.bb.width:0};r.Xd=function(){return this.a?this.a.height:this.bb?this.bb.height:0};r.Db=function(){return!!this.a};r.bc=function(){return!(!this.bb||!this.bb.complete)};r.Qb=function(){return this.g}; +r.Ib=function(a){if(this.g&&this.c){this.g=!1;var b=this.c,c=this.mimeType;if(!this.Db()&&!this.bc())if(1==a&&"image/x-dds"==c)ER(this,!1);else if(2==a&&"image/x-dds"==c)ER(this,!0);else if(2==a&&"image/png"==c)this.Db()||(DR||(DR=new vR),b=DR,b.data=this.b,b.a=8,b.g=[],b.o=null,b.b={},b.h=null,b.text={},b.s=0,b.j=0,b.m=null,b.width=0,b.height=0,b.f=0,b.l=0,b.c=0,b.i=!1,b.u=0,wR(b),a=new Uint8Array(b.width*b.height*4),CR(b,a,AR(b)),b=b.height,a=new VQ(a,a.length/b/4,b),this.c=this.b=null,this.a=a, +this.ld());else if(!this.Ab()){a=b.a;c=this.b;var d=null;b=aR(c);if(a.g)d=new x.Blob([c],{type:b});else if(a.f){var e=new a.c;d=c.buffer;if(0!=c.byteOffset||c.byteLength!=c.buffer.byteLength)d=c.buffer.slice(c.byteOffset,c.byteOffset+c.byteLength);e.append(d);d=e.getBlob(b)}e=go("IMG");d&&a.a&&a.b?(b=a.a(d),ec(e,"load",D(a.b,a,b))):(a=Dc(c),b="data:"+b+";base64,"+a);e.src=b;this.c=this.b=null;this.bb=e;e.complete?this.ld():this.f&&ec(e,"load",D(this.ld,this))}}}; +r.sd=function(a){var b=this.mimeType;return 1==a?"image/x-dds"==b:2==a?"image/x-dds"==b||"image/png"==b:3==a?"image/x-dds"!=b:!1};r.ld=function(){this.f&&(this.f(this),this.f=null)};function GR(){this.b=null;this.a=[]}var HR=new function(){this.a=new $Q};function eJ(a,b,c){if(B(a.a[c]))return a.a[c];b=Ly(b).Aa[c].getImageData();b=new FR(b,HR);return a.a[c]=b};function IR(a,b,c,d){this.a=a;this.o=b;this.s=c;this.m=d;this.b={};this.c=0;this.g={};this.h={};this.f={};this.j=[];this.i=[];this.l=0}function GK(a,b){var c=a.b[b];void 0===c&&(c=a.a[b]);return c}function SH(a,b){return RA(a.m,GK(a,b))}function CK(a,b){return RA(a.m,a.a[b])}function JR(a){for(var b=Object.keys(a.b),c=Array(b.length),d=0;d<b.length;d++)c[d]=a.b[parseInt(b[d],10)];return c};function KR(a,b,c){this.a=a;this.b=b;this.g=c;this.f=this.c=-1}function LR(a,b){return a.a!=b.a?a.a-b.a:a.b!=b.b?a.b-b.b:a.g-b.g}function MR(a,b,c){for(var d=0;d<a.length;){for(var e=a[d].a,f=a[d].b,g=d+1;g<a.length;g++){var h=a[g];if(h.a!=e||h.b!=f)break}for(e=d;e<g;e++)0>a[e].f?a[e].f=b:b=a[e].f,b+=c;for(e=d;e<g;e++)0>a[e].c?a[e].c=b:b=a[e].c,b+=c;d=g}};function NR(){this.c=!1;this.b=[];this.a=[]}function OR(a,b){a.c||(a.a.sort(LR),a.c=!0);for(var c=0;c<a.a.length;c++)a.a[c].f=-1,a.a[c].c=-1;if(b){b=b.a;a=a.a;c=Array(b.length+a.length);for(var d=0,e=0;;){var f=b[d],g=a[e];if(!f)break;if(!g)break;0<LR(f,g)?(c[d+e]=g,e++):(c[d+e]=f,d++)}for(;d<b.length;)c[d+e]=b[d],d++;for(;e<a.length;)c[d+e]=a[e],e++;MR(c,1,1)}else MR(a.a,10,10)};function PR(a){this.data=a||[]}F(PR,W);function fM(a){this.data=a||[]}F(fM,W);function QR(a){this.data=a||[]}F(QR,W);function RR(a,b,c,d){Pp.call(this);this.a=a;this.l=b;this.b=new OQ;this.m=[];this.o=[];this.i=[];this.u={};this.f=this.s=null;this.g=!1;this.h=null;this.j=c||new GR;this.v=d||null;this.B=SR++;this.A=null;this.c=16;this.c=AI(this.a);TR(this);UR(this)}F(RR,Pp);var SR=0; +RR.prototype.X=function(){var a=this.a;if(a){var b=a.c;b&&(b.c=null,b.a=null,b.b=null,b.f=null);a.c=null;if(b=a.u)b.b=null,b.a=null;a.u=null;if(a.b)for(b=0;b<a.b.length;b++){var c=a.b[b];if(c){c.f=null;if(c.a)for(var d=0;d<c.a.length;d++)fv(c.a[d]);c.a=null;c.g=null;c.j=null;c.h=null;c.c=null;if(c.b)for(d=0;d<c.b.length;d++)ev(c.b[d]);c.b=null;c.i=null}}a.b=null;if(b=a.h){b.b=null;b.c=null;b.f=null;if(b.a)for(c=0;c<b.a.length;c++)Tx(b.a[c]);b.a=null}a.h=null;if(a.f)for(b=0;b<a.f.length;b++)if(c=a.f[b])c.g= +null,c.b=null,c.a=null,c.h=null,c.f=null,c.c=null;a.f=null;a.C=null;if(b=a.o){if(b.a)for(c=0;c<b.a.length;c++)Qw(b.a[c]);b.a=null;cy(b.b);b.b=null}a.o=null;if(b=a.j){if(b.a)for(c=0;c<b.a.length;c++)sx(b.a[c]);b.a=null;cy(b.b);b.b=null}a.j=null;if(b=a.i){if(b.a)for(c=0;c<b.a.length;c++)Hx(b.a[c]);b.a=null;cy(b.b);b.b=null}a.i=null;if(b=a.l){if(b.a)for(c=0;c<b.a.length;c++)Au(b.a[c]);b.a=null;cy(b.b);b.b=null}a.l=null;if(b=a.a){if(b.Aa)for(c=0;c<b.Aa.length;c++)Mx(b.Aa[c]);b.Aa=null}a.a=null;if(b=a.A){if(b.a)for(c= +0;c<b.a.length;c++)Qx(b.a[c]);b.a=null;cy(b.b);b.b=null}a.A=null;if(b=a.v){if(b.a)for(c=0;c<b.a.length;c++)ey(b.a[c]);b.a=null}a.v=null;a.B=null;if(a.m)for(b=0;b<a.m.length;b++)if(c=a.m[b])c.b=null,c.a=null;a.m=null;a.s=null;if(a.g)for(b=0;b<a.g.length;b++)wd(a.g[b]);a.g=null}if(this.l)for(a=0;a<this.o.length;++a)b=this.l,c=this.o[a],d=b.c[c],!B(d)||0>d||(b.a[d]--,b.a[d]||(b.a[d]=-1-b.b,b.b=d,delete b.c[c],b.f&&b.f.call(b.g,d)))}; +function TR(a){if(null!=a.a.b&&a.v)for(var b=a.a.b,c=0;c<b.length;++c){var d=b[c],e=a.v,f=d,g=d.wa();d=a.m;var h=a.o,k=f;$u(k);var l=k.a?k.a.length:0;if(0!=l){var m=null,n=null,p=null,q=null;k=null;for(var t=[],v=[],u=[],w=[],y=[],A=0;A<l;A++){var z=f;var C=A;$u(z);C=z.a[C];z=null==f.c||f.c||1<l?C.getZoom():0;if(null!=C.c){var I=C;null===I.c&&(I.c=new Uu);I=I.c;n||(n=new zA);v.push(z);JB(I,z,n)}null!=C.a&&(I=C,null===I.a&&(I.a=new Ou),I=I.a,m||(m=new zA),t.push(z),EB(I,z,m));null!=C.g&&(I=C,null=== +I.g&&(I.g=new Yu),I=I.g,p||(p=new zA),u.push(z),KB(I,z,p));null!=C.b&&(I=C,null===I.b&&(I.b=new Pu),I=I.b,q||(q=new zA),w.push(z),GB(I,z,e.b,q));null!=C.f&&(null===C.f&&(C.f=new Zu),C=C.f,k||(k=new zA),y.push(z),DA(k,z,C))}n&&(LB(v,n),f=n.style,l="L"+g,h&&h.push(l),l=pr(e.a,l),f.B=l,d.push(f));m&&(LB(t,m),f=m.style,l="A"+g,h&&h.push(l),m=pr(e.a,l),f.B=m,d.push(f));p&&(LB(u,p),f=p.style,l="V"+g,h&&h.push(l),p=pr(e.a,l),f.B=p,d.push(f));q&&(LB(w,q),f=q.style,l="B"+g,h&&h.push(l),q=pr(e.a,l),f.B=q,d.push(f)); +k&&(LB(y,k),f=k.style,l="R"+g,h&&h.push(l),e=pr(e.a,l),f.B=e,d.push(f))}}} +function UR(a){var b=a.b;if(Ey(a.a)&&jy(Fy(a.a)))for(var c=Fy(a.a).a,d=0;d<c.length;d++){var e=c[d],f=null!=e.h?VR(a,null==e.h?"\u00ffffffff\u00ffffff\u00ffff\u00ff\u00ffffffff\u00ffffff\u00ffff\u00ff":e.h,!0,"L"):WR(a,null==e.m?-1:e.m,"L");f=RQ(b,e,1,d,0,f,null==e.s?0:e.s,null==e.u?0:e.u);if(e=e.getExtension(53863091))f.c=!0,null!=e.a&&(f.i=null==e.a?!1:e.a)}if(Gy(a.a)&&ly(Hy(a.a)))for(c=Hy(a.a).a,d=0;d<c.length;d++)if(e=c[d],f=null!=e.g?VR(a,null==e.g?"\u00ffffffff\u00ffffff\u00ffff\u00ff\u00ffffffff\u00ffffff\u00ffff\u00ff": +e.g,!0,"A"):WR(a,null==e.h?-1:e.h,"A"),f=RQ(b,e,2,d,0,f,null==e.i?0:e.i,null==e.j?0:e.j),e=e.getExtension(53863091))f.c=!0,null!=e.a&&(f.i=null==e.a?!1:e.a);if(null!=a.a.i&&ny(Iy(a.a)))for(c=Iy(a.a).a,d=0;d<c.length;d++)if(e=c[d],f=null!=e.f?VR(a,null==e.f?"\u00ffffffff\u00ffffff\u00ffff\u00ff\u00ffffffff\u00ffffff\u00ffff\u00ff":e.f,!0,"V"):WR(a,null==e.g?-1:e.g,"V"),f=RQ(b,e,3,d,0,f,null==e.h?0:e.h,null==e.i?0:e.i),e=e.getExtension(53863091))f.c=!0,null!=e.a&&(f.i=null==e.a?!1:e.a);if(Jy(a.a)&& +py(Ky(a.a)))for(c=Ky(a.a),d=0;d<(c.a?c.a.length:0);d++)if(e=c.a[d],f=null!=e.l?VR(a,Gu(e),!0,"B"):WR(a,null==e.i?-1:e.i,"B"),f=RQ(b,e,4,d,null==e.m?0:e.m,f,null==e.s?0:e.s,null==e.u?0:e.u),e=e.getExtension(53863091))f.c=!0,null!=e.a&&(f.i=null==e.a?!1:e.a);if(null!=a.a.a&&ry(Ly(a.a)))for(e=Ly(a.a).Aa,d=0;d<e.length;d++)c=e[d],f=null!=c.b?VR(a,null==c.b?"\u00ffffffff\u00ffffff\u00ffff\u00ff\u00ffffffff\u00ffffff\u00ffff\u00ff":c.b,!0,"R"):WR(a,null==c.f?-1:c.f,"R"),RQ(b,c,5,d,0,f,null==c.g?0:c.g,null== +c.h?0:c.h);if(Jy(a.a)&&py(Ky(a.a)))for(c=Ky(a.a),d=0;d<(c.a?c.a.length:0);d++)e=c.a[d],XR(a,e,d)} +function XR(a,b,c){if(null!=b.j){var d=a.b,e=-1;null!=b.l?e=VR(a,Gu(b),!0,"B"):null!=b.i&&(e=WR(a,null==b.i?-1:b.i,"B"));c=d.a[4][c];var f=Cu(b);if(null!=f.b||null!=f.c){var g=null!=f.b?VR(a,lu(f),!0,"B"):WR(a,null==f.c?-1:f.c,"B");g=SQ(d,c,g);c.j=g}YR(a,c,e,f,0);if(null!=b.a){b=Du(b);if(null!=b.b||null!=b.c)g=null!=b.b?VR(a,lu(b),!0,"B"):WR(a,null==b.c?-1:b.c,"B"),g=SQ(d,c,g),c.l=g;YR(a,c,e,b,1)}a.g=!0}} +function YR(a,b,c,d,e){for(var f=0;f<(d.a?d.a.length:0);f++){var g=d.a[f],h=c;null!=g.h?h=VR(a,null==g.h?"\u00ffffffff\u00ffffff\u00ffff\u00ff\u00ffffffff\u00ffffff\u00ffff\u00ff":g.h,!0,"B"):null!=g.i&&(h=WR(a,null==g.i?-1:g.i,"B"));g=SQ(a.b,b,h);0==e?(h=b,h.f||(h.f=[]),h.f.push(g)):(h=b,h.h||(h.h=[]),h.h.push(g))}} +function nN(a){var b=a.b.b.length;if(!a.f){a.f=new NR;for(var c=0;c<b;c++){var d=a.b.b[c];if(4!=d.a&&3!=d.a){d=a;var e=c,f=d.getZoom();d=oA(CK(d.s,e),f);e=a.f;f=c;for(var g=a.b.b[c].u,h=a.b.b[c].v,k=e.a,l=null,m=0;m<k.length;m++)if(k[m].a==d&&k[m].b==g&&k[m].g==h){l=k[m];break}l||(l=new KR(d,g,h),e.a.push(l));e.b[f]=l}}}a.h&&a.h.f?OR(a.f,a.h.f):OR(a.f);for(c=0;c<b;c++)d=a.b.b[c],4!=d.a&&3!=d.a&&(d.za=a.f.b[c].c,d.b=a.f.b[c].f)} +function VR(a,b,c,d){d+=b;if(c)return a.u[b]||(a.u[b]=!0,a.i.push(b)),pr(a.l,d);a=qr(a.l,d);return-1==a?0:a}function WR(a,b,c){if(null==a.a.b)return b;if(0>b)return 0;var d=a.a.b;if(b>=d.length)return 0;b=d[b];c=VR(a,b.wa(),(null==b.c?!0:b.c)&&!(null!=b.a||null!=b.g),c);0==c&&(tK(a),uK(a),a.getZoom());return c}function tK(a){a=Ay(a.a);return null==a.a?0:a.a}function uK(a){a=Ay(a.a);return null==a.b?0:a.b}RR.prototype.getZoom=function(){return Ay(this.a).getZoom()}; +function BL(a){var b=a.j;b.b?b=b.b:(a=Dy(a.a),Zx(a),a=new FR(a.b,HR),b=b.b=a);return b}function EL(a,b){var c=ay(Dy(a.a),b);return null!=c.a?null==c.a?"\x00\x00\x00\x00\x00\x00\x00\x00":c.a:"g_"+a.B+"_"+b} +function eM(a,b){if(a.O())return null;var c=a.b.b[b];c=4==c.a?zu(ZR(a,b)):1==c.a?Pw($R(a,b)):2==c.a?rx(aS(a,b)):3==c.a?Gx(bS(a,b)):null;if(!c)return null;a=a.b.b[b];if(2==a.a){a=new QR;if(b=Id(c,32819068))b=b.w(),a.data[5]=b;if(b=Id(c,42466818))b=b.w(),a.data[9]=b;if(b=Id(c,30096869))b=b.w(),a.data[4]=b;if(b=Id(c,52617685))b=b.w(),a.data[14]=b;if(b=Id(c,51650189))c=b.w(),a.data[13]=c;return a}if(1==a.a){a=new QR;if(b=Id(c,28517612))b=b.w(),a.data[1]=b;if(b=Id(c,30096869))b=b.w(),a.data[4]=b;if(b= +Id(c,48343962))b=b.w(),a.data[11]=b;if(b=Id(c,49095464))b=b.w(),a.data[12]=b;if(b=Id(c,132080860))b=b.w(),a.data[17]=b;if(b=Id(c,51650189))c=b.w(),a.data[13]=c;return a}if(4==a.a){a=new QR;if(b=Id(c,30929027))b=b.w(),a.data[3]=b;if(b=Id(c,66786615))b=b.w(),a.data[16]=b;if(b=Id(c,28517612))b=b.w(),a.data[1]=b;if(b=Id(c,30511227))b=b.w(),a.data[2]=b;if(b=Id(c,30096869))b=b.w(),a.data[4]=b;if(b=Id(c,33356690))b=b.w(),a.data[6]=b;if(b=Id(c,40251317))b=b.w(),a.data[7]=b;if(b=Id(c,43229016))b=b.w(),a.data[10]= +b;if(b=Id(c,51650189))b=b.w(),a.data[13]=b;if(b=Id(c,40154408))b=b.w(),a.data[8]=b;if(b=Id(c,60681369))b=b.w(),a.data[15]=b;if(b=Id(c,42466818))b=b.w(),a.data[9]=b;(b=Id(c,53863091))&&!xe(a,4)&&((new Ml(Ae(new PR(Ae(a,4)),0))).data[1]=null==b.b?"":b.b);return a}return 3==a.a?a=new QR:null}function AL(a,b,c,d){return XM(a.b.a[4][b],c,d)}function UM(a){var b;if(b=!a.h&&0==a.b.b.length&&0==a.m.length&&null==a.a.h)a=a.a,b=0==(a.f?a.f.length:0);return b} +function ZR(a,b){b=QQ(a.b,b);return Ky(a.a).a[b]}function $R(a,b){b=QQ(a.b,b);return Fy(a.a).a[b]}function aS(a,b){b=QQ(a.b,b);return Hy(a.a).a[b]}function bS(a,b){b=QQ(a.b,b);return Iy(a.a).a[b]}function mN(a,b,c){for(var d=PQ(a.b),e=Array(d),f=Array(d),g=0;g<d;++g)e[g]=a.b.G(g),f[g]=g>=a.b.b.length?!0:4==a.b.b[g].a;return new IR(e,f,b,c)};function cS(a,b){this.a=a;this.b=b};function dS(a){this.a=a};function eS(a,b){this.g=a;this.f=b;this.b=this.a=null;this.c=[];LQ("Roadmap")}eS.prototype.getData=function(a){if(!this.a)return[];a=new MP(0,a.a,0);for(var b=[],c=0;c<this.c.length;++c){var d=this.c[c];if(d.b()){var e=d.Md;if(OO(this))if(this.a.fb(e))d=new dS([new cS([e],a)]),b.push(d);else if(!d.a||"pending"!=d.a.getState()){d.a=this.a.ic(e,2,!0);var f=d.a.getState();"success"==f&&this.a.fb(e)?(d=new dS([new cS([e],a)]),b.push(d)):"pending"==f&&MM(d.a,this.f)}}}return b}; +function OO(a){a.b||(a.b=MQ(a.g,"Roadmap",3),"pending"==a.b.getState()&&MM(a.b,a.f));return"success"==a.b.getState()};function fS(){this.a=this.b=this.c=this.h=this.f=null;this.g=0}function gS(a){var b={};null!=a.f&&(b.uri=a.f);null!=a.h&&(b.xdc=a.h);null!=a.c&&(b.streaming=a.c);null!=a.b&&(b.chunked=a.b);null!=a.a&&(b.deferred=a.a);null!=a.g&&(b.workerOptions=a.g);return b}function hS(){this.i=this.g=this.h=this.a=this.c=this.f=this.b=this.status=null}function iS(a){return a?new VQ(a.data,a.width,a.height,a.format):null};function jS(a){this.f=a}jS.prototype.a=function(a){for(var b=0;b<this.f.length;++b)if(this.f[b].a(a))return!0;return!1};jS.prototype.b=function(a){for(var b=0;b<this.f.length;++b)if(this.f[b].a(a))return this.f[b].b(a);return null};jS.prototype.c=function(a,b,c){for(var d=0,e=0;e<this.f.length;++e){for(var f=[],g=[],h=0;h<a.length;++h)this.f[e].a(a[h].N)?f.push(a[h]):g.push(a[h]);a=g;0<f.length&&(this.f[e].c(f,b,c),d++)}};function kS(a){this.start=a;this.cancel=rr;this.b=null};function lS(a,b){this.type=a;this.N=b;this.data=B(void 0)?void 0:null;this.priority=2;this.result=new FM};function mS(a,b,c,d){this.h=a;this.g=b;this.f=c;this.i=d||!1}mS.prototype.a=function(a){return a.Ea()==this.g&&21>=a.getZoom()};mS.prototype.b=function(a){return this.a(a)?0:null};mS.prototype.c=function(a,b){for(var c=0;c<a.length;++c)nS(this,a[c],b)}; +function nS(a,b,c){if(b.N&&a.a(b.N)){var d=a.f.a(b.N),e=go("IMG");b.data=e;e.crossOrigin=a.i?"use-credentials":"";DG(a.h,new kS(function(a){var c=new no;c.cc(e,"load",function(){a();oS(e,b,c,!0)});c.cc(e,"error",function(){a();oS(e,b,c,!1)});e.src=d}),c)}else KM(b.result,"")}function oS(a,b,c,d){Lb(c);"pending"==b.result.getState()&&(d&&a.complete?HM(b.result,!0):KM(b.result))};function pS(){this.b=SE()}pS.prototype.a=function(a){a=qs.b(a.data,this.b);return"pb="+encodeURIComponent(a).replace(/%20/g,"+")};var qS={ae:!0,ar:!0,bh:!0,cn:!0,dz:!0,eg:!0,es:!0,gb:!0,gi:!0,gr:!0,"in":!0,iq:!0,jo:!0,jp:!0,kr:!0,kw:!0,lb:!0,ly:!0,ma:!0,mk:!0,mm:!0,om:!0,pk:!0,qa:!0,ru:!0,sa:!0,tn:!0,tr:!0,tw:!0,ua:!0,uk:!0};function rS(a){return!!a&&!!qS[a.toLowerCase()]};function sS(a){this.b=a}sS.prototype.a=function(a){for(var b=0,c=0;c<a.length;++c)b+=a.charCodeAt(c);return this.b[b%this.b.length].a(a)};function tS(a){if(1==a.length)a=new KF(a[0]);else{for(var b=Array(a.length),c=0;c<a.length;++c)b[c]=new KF(a[c]);a=new sS(b)}return a};function uS(a,b){this.c=b;this.f=tS(a);this.b=new pS}uS.prototype.a=function(a){var b=new QE;He(b,this.c);var c=a.ba().g;c&&rS(c)&&(TE(b).data[2]=c);c=new EE(De(b,0));OE(c).data[1]=iC(a);OE(c).data[2]=jC(a);c=OE(c);a=a.getZoom();c.data[0]=a;b=this.b.a(b);return this.f.a(b)};function vS(a){this.b=a}vS.prototype.a=function(a){a=a.Ha;var b=this.b;b=b[(a.b+a.a)%b.length];return b+=(-1==b.indexOf("?")?"?":"&")+"x="+a.b+"&y="+a.a+"&z="+a.getZoom()};function wS(){this.b=new pS}wS.prototype.a=function(a){var b=this.b.a(a);a:{if(a instanceof QE)for(var c=0;c<Fe(a,1);c++){var d=mC(a,c);if(2==ye(d,0,0)){a=!0;break a}}a=!1}return a?b+"&authuser=0":b};function xS(){}xS.prototype.b=function(a,b,c){for(var d=0;d<a.length;++d){var e=a[d].N;if(this.a(e)){var f=new EE(De(c,0));OE(f).data[1]=iC(e);OE(f).data[2]=jC(e);f=OE(f);e=e.getZoom();f.data[0]=e;b.push(a[d])}else KM(a[d].result,"")}};xS.prototype.a=function(a){return 0==a.Ea()&&22>=a.getZoom()};function yS(a,b,c,d){this.b=a;this.f=b;this.g=c;this.c=d;this.a=sa}function zS(a,b,c,d){B(b.xd)&&b.xd()&&B(b.vd)&&b.vd();b=a.f.a(b);var e=d||new xQ;e.start(a.c);a.b.a(b,function(b){try{3!=e.a&&(++e.c,1==e.c&&c(AS(a,b,e)))}catch(g){throw a.a(g),g;}},function(){try{3!=e.a&&(0==e.c&&(zQ(e,2),c(null)),e.done())}catch(f){throw a.a(f),f;}},e)} +function BS(a,b,c,d,e){b=a.f.a(b);var f=e||new xQ;f.start(a.c);a.b.a(b,function(b){try{if(3!=f.a){++f.c;var d=AS(a,b,f);null!=d&&c(d)}}catch(k){throw a.a(k),k;}},function(){try{3!=f.a&&(d&&d(),f.done())}catch(g){throw a.a(g),g;}},f)}function AS(a,b,c){var d=null;try{d=a.g.a(b)}catch(e){zQ(c,2),d=null}return d};function CS(a,b,c,d,e){b=new CQ(a,b);this.a=new yS(b,c,d,e)};function DS(a){return 255<a&&ES[a]?ES[a]:a}var ES,FS=[];FS[8364]=128;FS[8218]=130;FS[402]=131;FS[8222]=132;FS[8230]=133;FS[8224]=134;FS[8225]=135;FS[710]=136;FS[8240]=137;FS[352]=138;FS[8249]=139;FS[338]=140;FS[381]=142;FS[8216]=145;FS[8217]=146;FS[8220]=147;FS[8221]=148;FS[8226]=149;FS[8211]=150;FS[8212]=151;FS[732]=152;FS[8482]=153;FS[353]=154;FS[8250]=155;FS[339]=156;FS[382]=158;FS[376]=159;ES=FS;function GS(){this.b=2;this.a=0;this.c=-1;this.g=0;this.f=sa}var HS=function(){if(!pb||Ab(12))return!1;if(Ab(11)){var a=new Uint8Array(1);a[0]=128;a=x.URL.createObjectURL(new Blob([a]));var b=new XMLHttpRequest;b.open("GET",a,!1);b.overrideMimeType("application/octet-stream; charset=x-user-defined");b.send();x.URL.revokeObjectURL(a);if(128==(b.responseText.charCodeAt(0)&255))return!1}return!0}(); +function IS(a,b){for(a.g=b.length;;)switch(a.b){case 2:var c=a;b.length<c.a+4?c=!1:"X"!=b[c.a]||"H"!=b[c.a+1]||"R"!=b[c.a+2]||"1"!=b[c.a+3]?(c.b=1,c=!1):(c.a+=4,c.b=3,c=!0);if(!c)return!1;break;case 3:c=a;b.length<c.a+4?c=!1:(c.c=JS(b,c.a)<<24|JS(b,c.a+1)<<16|JS(b,c.a+2)<<8|JS(b,c.a+3),c.a+=4,0>c.c?(c.b=1,c=!1):(c.b=4,c=!0));if(!c)return!1;break;case 4:return b.length<a.a+a.c?b=!1:(a.f(b.substr(a.a,a.c)),a.a+=a.c,a.c=-1,a.b=3,b=b.length>a.a),b?!0:!1;default:return!1}} +function JS(a,b){return HS?DS(a.charCodeAt(b)):a.charCodeAt(b)&255};function KS(a,b,c,d){this.b=a;this.g=b;this.c=c;this.f=d||!1;this.a=null}KS.prototype.getData=function(){return this.c};function LS(a){this.b=a}LS.prototype.a=function(a){if(2>a.length)throw"Invalid number of bytes in streaming paint response";var b=2==a.length?null:a.subarray(2);return new KS(a[0],a[1],b,this.b)};function MS(a){this.b=a}MS.prototype.a=function(a,b,c,d){this.b.a(a,D(this.c,this,b,d),c,d)};MS.prototype.c=function(a,b,c){if(!b||3!=b.a&&2!=b.a){c=new Uint8Array(c,0,c.byteLength);if(4>c.length||88!=c[0]||72!=c[1]||82!=c[2]||49!=c[3])a=!1;else{for(var d=4;d+4<c.length;){var e=c[d]<<24|c[d+1]<<16|c[d+2]<<8|c[d+3];d+=4;if(d+e>c.length)break;var f=c.subarray(d,d+e);a(f);d+=e}a=d!=c.length?!1:!0}!a&&b&&zQ(b,2)}};function NS(a,b,c,d){b=new FQ(b,"arraybuffer");b.b=!!d;CS.call(this,a,new MS(b),c,new LS,"NonStreamedMegatilePaintService.streamingPaint")}F(NS,CS);NS.prototype.b=function(a,b,c,d){BS(this.a,a,b,c,d)};function OS(a,b){if(!a.D){var c=new QE;c.data[3]=1;var d=new YD(Ae(c,5));d.data[43]=a.c;d.data[0]=12;d.data[1]=2;d.data[49]=0;if(1==a.c&&a.h){var e=new OD(Ae(c,4));e.data[0]=4;e=new WD(Ae(e,7));Ce(e,0).push(0);Ce(e,0).push(1)}2==a.c&&a.g&&(d.data[27]=3);e=Yn(a.la,1,2);1!=e&&((new $D(Ae(d,29))).data[0]=e);a.ha&&Ce(d,40).push(1);TE(c).data[4]=a.C;for(d=0;d<a.l.length;++d)e=a.l[d],Ce(c,22).push(e);a.D=c}this.b=a.D;this.c=a.B;this.a=b} +function PS(a,b,c){var d=new QE;He(d,a.b);var e=new YD(Ae(d,5)),f=b[0].N;a.c&&(gC(f)?e.data[10]=2:(new hE(Ae(e,25))).data[3]=!0);Ls(f.ba().c)&&(e.data[38]=!0);e=b[0].N.ba();f=e.a;for(var g=f.a.length,h=Array(g),k=0;k<g;++k)h[k]=Array(b.length);for(k=0;k<b.length;++k)for(var l=b[k].N.b,m=0;m<l.length;++m)h[m][k]=l[m];for(k=0;k<g;++k){l=null;if(e.f?e.a.b[k]:1)l=e.f?(l=e.a.b[k])?(l=e.f.a[l])?l.a.g(h[k]):null:null:null;-1!=l&&(m=UE(d),He(m,f.a[k]),null!==l&&(m.data[2]=l))}e=TE(d);f=b[0].N;g=f.ba().c; +for(h=0;h<g.a.length;++h)He(new Sn(De(e,11)),g.a[h]);f.ba().h&&(e.data[1]=f.ba().h);(g=f.ba().g)&&(gC(f)||rS(g))&&(e.data[2]=g);a.a.b(b,c,d);return d};function QS(a){this.f=a}QS.prototype.a=function(a){return this.f.a(a)};QS.prototype.b=function(a){return this.f.b(a)}; +QS.prototype.c=function(a,b,c){if(0!=a.length){var d=a;for(a=[];0<d.length;){for(var e=[],f=d[0].N,g=[d[0]],h=1;h<d.length;++h){var k=d[h].N,l=k;if(l=f.Ea()==l.Ea()){l=f.ba();var m=k.ba();l=l.h==m.h&&l.g==m.g}if(l)a:if(l=f.ba().a,m=k.ba().a,l.a.length!=m.a.length)l=!1;else{for(var n=0;n<l.a.length;++n)if(!Gs(l.a[n],m.a[n])){l=!1;break a}l=!0}l&&Ks(f.ba().c,k.ba().c)?g.push(d[h]):e.push(d[h])}a.push(g);d=e}RS(a.length);for(d=0;d<a.length;++d)this.f.c(a[d],b,c)}};var RS=sa;function SS(a,b,c,d){this.a=c;this.b=d}SS.prototype.start=function(){this.b?this.a.call(this.b):this.a();return Dr};function TS(){this.a=this.b=this.c=null};function US(a,b,c){this.h=a;this.f=b;this.g=c}US.prototype.a=function(a){return this.f.a.a(a)};US.prototype.b=function(a){return this.f.a.a(a)?5:null}; +US.prototype.c=function(a,b){if(0!=a.length){var c=[],d=PS(this.f,a,c);if(0<Fe(d,0)){var e=new xQ;AQ(e,b);var f=function(a){if(1==e.a&&a&&0==a.g){var b=a.b;0>b||b>=c.length||(b=c[b],"pending"==b.result.getState()&&(b.data=new TS,a.f?b.data.b=a.getData():b.data.c=a.getData(),b.data.a=a.a,HM(b.result,!0)))}},g=this.g.j(),h=function(){g();VS(c,e)},k=this.h;this.g.ed(new WS(function(){k.b(d,f,h,e)}),b-1);for(a=0;a<c.length;++a)b=c[a],"pending"==b.result.getState()&&XS(this,b,c,e)}}}; +function XS(a,b,c,d){LM(b.result,function(){for(var a=!1,b=0;b<c.length;++b){var g=c[b].result;if("pending"==g.getState())return;a=a||JM(g)}a&&d.cancel()&&VS(c,d)},a)}function VS(a,b){for(var c=0;c<a.length;++c){var d=a[c].result;"pending"==d.getState()&&(3==b.a?d.cancel():KM(d))}}function WS(a){this.a=a;this.b=void 0}F(WS,SS);function YS(a,b,c,d){d=!!d;b=new FQ(b,"arraybuffer");b.b=d;CS.call(this,a,b,c,new ZS,"SingleTilePaintService.streamingPaint")}F(YS,CS);YS.prototype.b=function(a,b,c,d){zS(this.a,a,function(a){a&&b(a);c&&c()},d)};function ZS(){}ZS.prototype.a=function(a){return new KS(0,0,a)};function $S(a,b,c){this.s=a;this.o=b;this.h=c;this.l=1;this.a=aT(this);this.i="";this.j=500;this.c=!1;this.b=null;this.f=0;this.g=!1}function bT(a,b,c){B(c)&&(a.l=c);a.g=!0;rD(a.a,b,void 0,void 0);a.g=!1}function cT(a){return a.a?BD(a.a):a.i}function dT(a){return a.a?zD(a.a):a.j}$S.prototype.cancel=function(){var a=this.a;eT(this,!1);a&&a.abort()}; +function aT(a){var b=new mD;b.g=Math.max(0,0);dc(b,"readystatechange",function(){fT(this,!1)},void 0,a);dc(b,"success",function(){fT(this,!0)},void 0,a);dc(b,"error",a.m,void 0,a);dc(b,"abort",a.m,void 0,a);return b}function fT(a,b){b&&eT(a,!0);if(!(a.c||null!==a.b||a.g&&0==cT(a).length)){var c=E();!b&&10>c-a.f?a.b=x.setTimeout(function(){gT(a)},a.f+10-c):gT(a)}}function gT(a){a.b=null;if(a.h)a.c=!0,a.h.Mb(a,a.l);else for(var b=a.start();b!==Dr;)b=b.apply(a)} +$S.prototype.start=function(){this.f=E();if(this.s())return this.start;this.c=!1;return Dr};$S.prototype.m=function(){this.o();eT(this,!1)};function eT(a,b){!b&&a.c&&(a.c=!1,a.h.Pe(a));null!=a.b&&(x.clearTimeout(a.b),a.b=null);a.a&&(a.i=BD(a.a),a.j=zD(a.a),nc(a.a),a.a=null)};function hT(a,b){this.g=a;this.h=!!b;this.f=this.a=this.b=null;this.c=new GS}function iT(a,b,c,d,e){a.b=new $S(D(a.i,a),D(a.j,a),a.g);a.a=e||null;a.c.f=c;a.f=d||sa;if(e){var f=a.b;yQ(e,function(){f.cancel();return!0})}a.b.a.l=a.h;bT(a.b,b,e?jT(e.b):void 0)}hT.prototype.i=function(){if(null!=this.a&&3==this.a.a)return!1;var a=cT(this.b);a=IS(this.c,a);!a&&null===this.b.a&&kT(this);return a};hT.prototype.j=function(){null!=this.a&&3==this.a.a||kT(this)}; +function kT(a){var b=a.c;if(3!=b.b||b.g>b.a||!NC(dT(a.b)))switch(dT(a.b)){case 400:a.a&&zQ(a.a,4);break;case 404:a.a&&zQ(a.a,5);break;default:a.a&&zQ(a.a,2)}a.f()}function jT(a){switch(a){case 3:return 2;case 2:return 1;case 1:return 0;default:return 1}};function lT(a,b){this.f=pa(a)||a instanceof mB?new EQ(a):a;this.c=b;this.b=!1}lT.prototype.a=function(a,b,c,d){var e=new hT(this.c,this.b);a=this.f.a(a);iT(e,a,b,c,d)};function mT(a,b,c,d,e){b=new lT(c,b);b.b=!!e;CS.call(this,a,b,d,new nT,"StreamingPaintService.streamingPaint")}F(mT,CS);mT.prototype.b=function(a,b,c,d){BS(this.a,a,b,c,d)};function nT(){} +nT.prototype.a=function(a){if(2>a.length)throw"Invalid number of bytes in streaming paint response";var b=JS(a,0),c=JS(a,1);var d=B(void 0)?NaN:a.length;d>a.length&&(d=a.length);if(2>=d||2>=a.length)a=null;else{var e=new Uint8Array(d-2);if(HS)for(var f=2;f<d;++f)e[f-2]=DS(a.charCodeAt(f));else for(f=2;f<d;++f)e[f-2]=a.charCodeAt(f)&255;a=e.buffer}return new KS(b,c,a)};function oT(){}oT.prototype.b=function(a,b,c){a.sort(pT);for(var d=0;d<a.length;++d)if(this.a(a[d].N)){var e=new qT,f=rT(this,e,a,d);sT(this,d,f,e,c,a,b);d=f-1}else KM(a[d].result,"")};oT.prototype.a=function(a){return 0==a.Ea()&&22>=a.getZoom()};function qT(a,b,c,d){this.a=a;this.b=b;this.c=c;this.f=d}qT.prototype.reset=function(a,b,c,d){this.a=a;this.b=b;this.c=c;this.f=d};function tT(a,b){return iC(b)>=a.a&&iC(b)<=a.c&&jC(b)>=a.b&&jC(b)<=a.f} +qT.prototype.split=function(a,b){var c=this.c-this.a+1,d=this.f-this.b+1;return a&&b?[new qT(this.a,this.b,this.a+c/2,this.b+d/2),new qT(this.a+c/2+1,this.b,this.c,this.b+d/2),new qT(this.a,this.b+d/2,this.a+c/2,this.f),new qT(this.a+c/2+1,this.b+d/2,this.c,this.f)]:a?[new qT(this.a,this.b,this.a+c/2,this.f),new qT(this.a+c/2+1,this.b,this.c,this.f)]:b?[new qT(this.a,this.b,this.c,this.b+d/2),new qT(this.a,this.b+d/2,this.c,this.f)]:[]}; +function pT(a,b){a=a.N;b=b.N;var c=uT(a.getZoom(),b.getZoom());if(0!=c)return c;c=uT(jC(a),jC(b));return 0!=c?c:uT(iC(a),iC(b))}function rT(a,b,c,d,e,f){for(var g=B(e)?e:c.length,h,k,l,m,n=c[d].N.getZoom();d<g;++d){var p=c[d].N;if(a.a(p)){if(!B(e)&&p.getZoom()!=n){g=d;break}if(!B(f)||tT(f,p))B(h)?(h=Math.min(h,iC(p)),k=Math.min(k,jC(p)),l=Math.max(l,iC(p)),m=Math.max(m,jC(p))):(h=iC(p),k=jC(p),l=h,m=k)}}B(h)&&b.reset(h,k,l,m);return g}function uT(a,b){return a<b?-1:a>b?1:0} +function sT(a,b,c,d,e,f,g){var h=d.c-d.a+1,k=d.f-d.b+1;if(64>=h&&64>=k){e=new AE(Ae(new EE(De(e,0)),7));k=f[b].N;(new Oz(Ae(e,0))).data[1]=d.a;(new Oz(Ae(e,0))).data[2]=d.b;var l=new Oz(Ae(e,0));k=k.getZoom();l.data[0]=k;e.data[1]=h;for(h=b;h<c;++h)if(k=f[h].N,a.a(k)){if(tT(d,k)){b=e;l=(jC(k)-X(new Oz(b.data[0]),2))*X(b,1)+(iC(k)-X(new Oz(b.data[0]),1));k=Math.floor(l/32);l%=32;if(Fe(b,2)<k+1)for(var m=Fe(b,2);m<k+1;++m)Ce(b,2).push(0);m=k;0!=(Ce(b,2)[m]&1<<l)?b=!1:(m=k,m=Ce(b,2)[m],l=(m|1<<l)>>> +0,Ce(b,2)[k]=l,b=!0);b?g.push(f[h]):KM(f[h].result,"Could not be handled by TileBitmapPaintRegionBuilder.")}}else KM(f[h].result,"")}else for(d=d.split(64<h,64<k),k=[],h=0;h<d.length;++h)k=k.concat(vT(a,b,c,d[h],e,f,g))}function vT(a,b,c,d,e,f,g){var h=new qT;rT(a,h,f,b,c,d);B(h.a)&&sT(a,b,c,h,e,f,g)};function wT(a,b,c,d,e){this.f=pa(b)||b instanceof mB?new EQ(b):b;this.h=c;this.g=d;this.b=!1;this.c=a;this.i=e}wT.prototype.a=function(a,b,c,d){a=this.f.a(a);xT(new yT(this.b,this.h,this.g,this.i),a,b,this.c,c,d)};function yT(a,b,c,d){this.c=a;this.g=b;this.f=c;this.h=d;this.a=null}function xT(a,b,c,d,e,f){a.a=f||null;c=D(a.b,a,c,e||sa);e=new fS;e.f=b;e.h=a.c;e.c=a.g;e.b=a.f;e.g=a.h;var g=new rF(gS(e),c);f&&yQ(f,function(){d.abort(g);return!0});EF(d,g)} +yT.prototype.b=function(a,b,c,d){if(null==this.a||3!=this.a.a){var e=new hS;B(c.status)&&(e.status=c.status);B(c.prIndex)&&(e.b=c.prIndex);B(c.prStatus)&&(e.f=c.prStatus);B(c.prData)&&(e.c=c.prData);B(c.prChunks)&&(e.a=c.prChunks);B(c.spritemapImage)&&(e.h=iS(c.spritemapImage));if(B(c.rasterRenderOpImages))for(var f=e.g=[],g=0;g<c.rasterRenderOpImages.length;g++)f[g]=iS(c.rasterRenderOpImages[g]);B(c.computedWaterCoverage)&&(e.i=iS(c.computedWaterCoverage));null==e.b&&null==e.a||a(e);d&&(a=e.status, +!this.a||2!=a&&4!=a&&5!=a||zQ(this.a,a),b())}};function zT(a,b,c,d,e,f,g){a=new wT(a,c,!1,!0,e);a.b=!!g;a=new AT(a);CS.call(this,b,a,d,new LS(!0),"WorkerNonStreamedMegatilePaintService.streamingPaint")}F(zT,CS);zT.prototype.b=function(a,b,c,d){BS(this.a,a,b,c,d)};function AT(a){this.b=a}AT.prototype.a=function(a,b,c,d){this.b.a(a,D(this.c,this,b,d),c,d)};AT.prototype.c=function(a,b,c){if(!b||3!=b.a&&2!=b.a)for(b=c.a,c=0;c<b.length;c++)a(b[c])};function BT(){this.a=this.Oe=null};function CT(a){this.a=a}F(CT,WQ);r=CT.prototype;r.Ab=function(){return null};r.Yb=function(){return this.a};r.Yd=function(){return this.a.width};r.Xd=function(){return this.a.height};r.Db=function(){return!0};r.bc=function(){return!1};r.Qb=function(){return!1};r.Ib=function(){};r.sd=function(){return!1};function DT(){}DT.prototype.a=function(a){var b=new KS(a.b,a.f,a.c,!0);b.a=new BT;var c=b.a;var d=a.h;var e=a.g;if(d||e){var f=new GR;if(d){var g=new CT(d);f.b=g}if(e)for(d=0;d<e.length;d++)if(g=e[d])g=new CT(g),f.a[d]=g;e=f}else e=null;c.Oe=e;b.a.a=a.i;return b};function ET(a,b,c,d,e,f,g){a=new wT(a,c,!1,!1,e);a.b=!!g;CS.call(this,b,a,d,new DT,"WorkerSingleTilePaintService.streamingPaint")}F(ET,CS);ET.prototype.b=function(a,b,c,d){zS(this.a,a,function(a){a&&b(a);c&&c()},d)};function FT(a,b,c,d,e,f,g){a=new wT(a,c,!0,!0,e);a.b=!!g;CS.call(this,b,a,d,new DT,"WorkerStreamingPaintService.streamingPaint")}F(FT,CS);FT.prototype.b=function(a,b,c,d){BS(this.a,a,b,c,d)};function GT(a){this.f=a}GT.prototype.a=function(a){return this.f.a(a)};GT.prototype.b=function(a){return this.f.b(a)};GT.prototype.c=function(a,b,c){for(var d=0;d<a.length;++d)this.f.c([a[d]],b,c)};function HT(a,b,c,d,e){var f,g=new wS,h=NF(b)&1;switch(a){case 1:var k=tS(b.j);h?f=new ET(b.b,c,k,g,NF(b),e,b.a):f=new YS(c,k,g,b.a);return new GT(new US(f,new OS(b,new xS),d));case 2:case 3:case 0:return k=tS(b.O),3==a?h?f=new zT(b.b,c,k,g,NF(b),e,b.a):f=new NS(c,k,g,b.a):h?f=new FT(b.b,c,k,g,NF(b),e,b.a):f=new mT(c,d,k,g,b.a),b=new OS(b,new oT),2==a?new GT(new US(f,b,d)):new QS(new US(f,b,d));default:throw"Invalid fetcher type "+a;}};function IT(a,b,c,d){this.f={};this.h=!0;this.f[0]=HT(0,a,b,c,d);this.f[1]=HT(1,a,b,c,d);this.f[2]=HT(2,a,b,c,d);this.f[3]=HT(3,a,b,c,d);this.g=a.J}IT.prototype.a=function(a){return(this.f[this.g]||this.f[0]).a(a)};IT.prototype.b=function(a){return(this.f[this.g]||this.f[0]).b(a)};IT.prototype.c=function(a,b,c){var d=this.g,e=this.f[this.g];4==d&&(c?d=3:(d=!1,gC(a[0].N)?d=!0:this.h&&(this.h=!1,d=!0),d=d?0:1),e=this.f[d]);JT(d);e.c(a,b,c)};var JT=sa;function KT(a,b){this.a=a;this.result=b}function LT(a){this.i=a;this.f=[]}function MT(a,b){if("success"!=b.result.getState())return aN();var c=b.priority,d=a.f[c];d||(d=new NT(a,a.i,c),a.f[c]=d);a=new FM;d.a.push(new KT(b,a));d.f.Mb(d,d.c);return a}function NT(a,b,c){this.f=b;this.b=a;this.c=c;this.a=[]} +NT.prototype.start=function(){if(!this.a.length)return Dr;for(var a=this.a.shift();"pending"!=a.result.getState();){if(!this.a.length)return Dr;a=this.a.shift()}this.b.c(a.a,a.result);return this.a.length?this.start:Dr};function OT(a,b){LT.call(this,a);this.b=b}F(OT,LT);OT.prototype.a=function(a){for(var b=0;b<this.b.length;++b){var c=this.b[b].a(a);if(null!==c)return c}return null};function PT(a){this.a=a}F(PT,WQ);r=PT.prototype;r.Ab=function(){return this.a};r.Yb=function(){return null};r.Yd=function(){return this.a.width};r.Xd=function(){return this.a.height};r.Db=function(){return!1};r.bc=function(){return!B(this.a.complete)||this.a.complete};r.Qb=function(){return!1};r.Ib=function(){};r.sd=function(){return!1};function QT(a){LT.call(this,a)}F(QT,LT);QT.prototype.a=function(a){return 0!=a.type?null:MT(this,a)};QT.prototype.c=function(a,b){var c=a.N,d=new GR;d.a[0]=new PT(a.data);var e=a.data.width/256;a=new Mw;By(a).a=iC(c);By(a).b=jC(c);var f=By(a),g=c.getZoom();f.c=g;wy(a).a=e;null===a.a&&(a.a=new Jw);e=a.a;f=new uw;e.Aa=e.Aa||[];e.Aa.push(f);d=new RR(a,null,d);HM(b,new pO(c,d))};function RT(a,b,c){c=b+c;var d=b+3&-4,e=c&-4;if(e>d){var f=e-d>>2,g=new Uint8Array(a);for(a=new Int32Array(a,d,f);b<d;b++)g[b]^=155;for(b=0;b<f;b++)a[b]^=2610666395;b=e}else g=new Uint8Array(a);for(;b<c;b++)g[b]^=155};function ST(a,b,c,d,e){LT.call(this,a);this.g=b;this.j=c;this.b=B(e)?e:null;this.h=d||null}F(ST,LT);ST.prototype.a=function(a){return 5!=a.type?null:MT(this,a)}; +ST.prototype.c=function(a,b){var c=a.data;a=a.N;var d=null,e=null,f=!0;if(c){if(c.b){var g=c.b;f=!1}else g=c.c;c.a&&(d=c.a.Oe,e=c.a.a)}g&&g instanceof ArrayBuffer&&(g=new Uint8Array(g));var h=g&&0==g.length;if(null==c||null==g||h)e=new Mw,By(e).a=iC(a),By(e).b=jC(a),g=By(e),d=a.getZoom(),g.c=d,wy(e).a=this.g,e=new RR(e,null,void 0,this.h||void 0),HM(b,new pO(a,e));else{f&&(c=g,f=B(void 0)?void 0:0,c.buffer?RT(c.buffer,c.byteOffset+f,c.length-f):RT(c,f,c.byteLength-f));d=d||void 0;c=new Mw;g=gd(g); +uy(c,g);hd(g);wy(c).a=this.g;g=new RR(c,this.j,d,this.h||void 0);if(iC(a)!=tK(g)||jC(a)!=uK(g)||a.getZoom()!=g.getZoom())throw e=Error("ParsingFailed"),e.file=a.aa(),e.name="TileError",KM(b),e;null!==this.b&&(d=g.a,null==d.s||this.b!=(null==d.s?0:d.s))&&(KM(b),c=Error(),c.message="EpochMismatch,"+(null==d.s?0:d.s)+","+this.b,nF(c));e&&(g.A=e);HM(b,new pO(a,g))}};function TT(a){this.b=a}TT.prototype.a=function(a,b,c){var d=new xQ,e=new FM;e.wait(function(a){JM(a)&&d.cancel()});AQ(d,b);UT(this.b,a,function(b){1!=d.a?(c(a,null),KM(e,"")):(c(a,b),HM(e,!0))},d);return e};function VT(a){this.data=a||[]}F(VT,W);function WT(a){this.data=a||[]}F(WT,W);function XT(){this.c=WT;this.b=sa}XT.prototype.a=function(a){")]}'\n"==a.substr(0,5)&&(a=a.substr(5));try{var b=JSON.parse(a)}catch(c){}if(!(b instanceof Array))throw this.b(a),Error("JspbDeserializer parse error.");return new this.c(b)};function YT(a,b,c){var d=new wS;c=!!c;b=new FQ(b);b.b=c;this.a=new yS(new CQ(a,b),d||new pS,new XT,"PertileService.paint")}function UT(a,b,c,d){zS(a.a,b,c,d)};function ZT(a){this.b=a} +ZT.prototype.a=function(a,b,c){a:{var d=Fe(a,1);if(!(2>d)){d=Array(d);for(var e=0;e<d.length;++e){d[e]=mC(a,e);for(var f=d[e].wa(),g=0;g<e;++g)if(d[g].wa()==f){d=!0;break a}}}d=!1}if(!d)return this.b.a(a,b,c);e=Array(Fe(a,1));for(f=0;f<e.length;++f)e[f]=mC(a,f);d=[];for(f=e.length-1;0<=f;--f){g=e[f].wa();for(var h=f-1;0<=h;--h)if(g==e[h].wa()){var k=new QE;He(k,a);Be(k,1);He(UE(k),mC(a,h));d.push(k);k=h;Ce(a,1).splice(k,1);--f}}d.push(a);a=Array(d.length);for(e=0;e<d.length;++e)a[e]=this.b.a(d[e], +b,c);b=RM.apply(null,a);b.wait(cN,void 0);return b};function $T(){rc.call(this)}F($T,rc);function aU(a){Qb.call(this,"ViewportLoaded",a)}F(aU,Qb);function bU(a,b){Qb.call(this,"ViewportMissingData",a);this.c=b}F(bU,Qb);bU.prototype.mb=function(){return this.c};function cU(a){Qb.call(this,"ViewportReady",a)}F(cU,Qb);function dU(a,b){rc.call(this);this.b=a;this.c=b}F(dU,$T); +function eU(a,b,c,d,e,f,g,h,k){var l=[],m=[];b=fU(a.b,c,b);c=l;for(var n=m,p=0;p<d.length;++p){var q=d[p],t=b?gU(b,q):null;t?a.a(t,k)?c.push(t):(h.push(q),t=null):(g.push(q),t=null);t||((t=b?hU(a,b,q,k):null)?c.push(t):n.push(q))}f&&0<m.length&&(l=[],m=d.slice());if(0<m.length&&!a.c){if(k)for(d=m,f=l,g=0;g<e.length;g++)if(h=e[g],h.data&&k.fb(h)){c=h.N;n=!1;for(p=0;p<d.length;p++)if(q=d[p],c.a!=q.a?0:cC(c.Ha,q.Ha))n=!0,c.getZoom()<=q.getZoom()&&(d.splice(p--,1),c.getZoom()!=q.getZoom()&&f.push(sO(q, +c.getZoom())));n&&f.push(h)}if(0<m.length&&b)a:{e=m;d=l;f=Array(e.length);for(g=0;g<e.length;++g)f[g]=e[g].Ha;if(c=bC(f))for(n=e[0].getZoom(),p=Math.max(0,n-1),q=n-p,f=c.oa>>q,g=c.Yc>>q,h=c.xc>>q,c=c.bd>>q,n=6>n?0:6;p>=n;--p){0==p&&(g=f=0);for(q=f;q<=g;++q)for(t=h;t<=c;++t){for(var v,u=null,w=0;w<e.length;++w)if(iU(q,t,p,e[w])){if(!(u||(v=e[w],v=new dC(new kC(q,t,p),v.a,v.c),u=gU(b,v),u&&a.a(u,k))||(u=hU(a,b,v,k),u)))break;u&&(d.push(sO(e[w],p)),e.splice(w--,1))}u&&d.push(u);if(0==e.length)break a}f>>= +1;g>>=1;h>>=1;c>>=1}}}for(a=0;a<m.length;a++)l.push(sO(m[a],-1));return l}function hU(a,b,c,d){var e=c.Ha.aa(),f=b.a[e];c=f&&!fC(f.N,c)?f:(b=b.b[e])&&!fC(b.N,c)?b:null;return c&&a.a(c,d)?c:null}function iU(a,b,c,d){var e=d.getZoom()-c;if(b!=jC(d)>>e)return!1;b=1<<c;a>=b&&(a-=b);return a==iC(d)>>e}dU.prototype.a=function(a,b){return!b||b.fb(a)?!0:!1};function jU(a,b){dU.call(this,a,b)}F(jU,dU);jU.prototype.a=function(a,b){return gC(a.N)&&a.data&&!UM(a.data)&&!a.b?!1:jU.R.a.call(this,a,b)};function kU(a,b,c,d){this.f=0;this.a={};this.b={};this.g=a;this.h=b;this.c=c;this.i=d}function lU(a,b){a&&fC(a.N,b)||(a=null);return a}function mU(a,b,c){var d=b.N;a.i&&hC(d);var e=gU(a,d);if(!e||!fC(d,e.N)){e=d.Ha.aa();var f=a.a[e];if(!f)a.a[e]=b,a.f++;else if(!fC(f.N,d)){var g=a.b[e];g&&nU(a,a.b,g.N,!1);a.a[e]=b;a.b[e]=f;a.f++}b.a.Oa=!0;b.a.$a=!!c;b.a.Ca=a.c.add(1,function(){nU(a,a.b,d,nU(a,a.a,d,!1))},1);a.g(b);c?EO++:FO++}} +function nU(a,b,c,d){var e=c.Ha.aa(),f=b[e];if(!f||!d&&!fC(f.N,c))return!1;delete b[e];a.f--;a.h(f);Vp(a.c,f.a.Ca);f.a&&f.a.$();f.data&&f.data.$();return!0}function gU(a,b){var c=b.Ha.aa(),d=lU(a.a[c],b);d||(d=lU(a.b[c],b));if(!d||!d.data)return null;Wp(a.c,d.a.Ca);d.b&&Wp(a.c,d.b.a.Ca);return d};function oU(a,b){rc.call(this);this.a={};this.b=new Rp;Tp(this.b,a);this.h=b;this.f=D(this.g,this);this.c=D(function(a){this.dispatchEvent(new TO(this,[a]))},this)}F(oU,rc);oU.prototype.g=function(a){a=a.N;a.f||(a.f=eC(a.a,a.c));a=a.f;var b=this.a[a];b&&0==b.f&&(nc(b),delete this.a[a])};function fU(a,b,c){b=eC(b,c);return a.a[b]||null};function pU(a,b){this.b=a;this.a=b}function qU(a,b,c){"success"==b.getState()?a=rU(a,b.na().N,c):(a=PM(b,function(a){return rU(this,a.na().N,c)},a),a.wait(cN,void 0));return a}function rU(a,b,c){if(b){var d=fU(a.b,b.Ea(),b.ba());if(d&&(b=gU(d,b)))if(a.a.fb(b)){var e=new FM;HM(e,b)}else e=a.a.ic(b,c)}e||(e=new FM,KM(e,""));return e};function sU(a,b,c,d,e,f){this.h=a;this.o=b;this.f=new no(this);Qp(this,this.f);po(this.f,d,"ViewportMissingData",this.i,!1,this);po(this.f,d,"ViewportReady",this.j,!1,this);this.l=e;this.m=f;this.b=!0;this.g=c;this.c=this.a=null}F(sU,Pp);function tU(a,b,c,d,e,f){b=a.h.a(b,c,d,e,a.g,f);b=uU(a,b,!0);if("pending"==b.getState()){var g=a.m;SO(g);b.wait(function(){g.a--;g.b&&0==g.a&&g.b(1)})}a.a&&a.a.cancel();a.a=b;a.b=!1;return a.a} +function uU(a,b,c){for(var d=[],e=0;e<b.length;e++)for(var f=a.o.a(b[e]),g=0;g<f.length;++g){var h=f[g];"success"!=h.getState()&&d.push(h)}if(!d.length)return $M();1==d.length?b=d[0]:(b=RM.apply(null,d),b.wait(cN,void 0));c&&a.l(d);return b}sU.prototype.i=function(a){this.c=a;this.b&&vU(this,a)}; +function vU(a,b){var c=b.mb();for(b=[];0<c.length;){var d=[],e=c[0],f=e.Ea(),g=e.ba();e=[e.Ha];for(var h=1;h<c.length;++h){var k=c[h];Ps(g,k.ba())&&f==k.Ea()?e.push(k.Ha):d.push(k)}b.push(new qQ(e,g,f,2,3,!1,!1));c=d}c=a.a;a.a=uU(a,b,!0);c&&c.cancel()}sU.prototype.j=function(){this.c=null;this.b&&(this.a&&this.a.cancel(),this.a=null)};function wU(a,b,c){this.b=a;this.c=b;this.f=c} +wU.prototype.a=function(a){if(0!=a.b||!a.a.b)return this.b.a(a);for(var b=a.c,c=Array(b.length),d=a.a.b,e=[],f=[],g=0;g<b.length;++g){var h=b[g];xU(h,a.a,d)&&(e.push(h),c[g]=new FM,f.push(c[g]))}if(0==e.length)return this.b.a(a);h=[];d=[];if(e.length<b.length){for(g=0;g<b.length;++g)c[g]||(h.push(b[g]),d.push(g));b=this.b.a(rQ(a,h));for(g=0;g<b.length;++g)c[d[g]]=b[g]}var k=this;this.c.Mb(new yU(function(){for(var b=0;b<e.length;++b){var c=f[b];if("pending"==c.getState()){var d=e[b];var g=k;var h= +d.b,t=d.a,v=d.getZoom(),u=new Mw;By(u).a=h;By(u).b=t;By(u).c=v;wy(u).a=g.f;g=new RR(u,null);HM(c,new pO(new dC(d,a.b,a.a),g))}}}),a.priority);return c};function xU(a,b,c){b=Fs(b.a,a,b.f);a=Fs(c.a,a,c.f).length;if(a==b.length)return!0;for(;a<b.length;++a)if(-1!=b[a])return!1;return!0}function yU(a){this.a=a;this.b=void 0}F(yU,SS);function zU(a,b,c){this.f=a;this.c=b;this.b=c}function AU(a,b){b=b.na();a=a.na();a.b=b;var c=a.data;b=b.data;c.h!==b&&(c.h=b);return a}zU.prototype.a=function(a){var b=this.c.a(a);if(0!=a.b||!a.a.b)return b;a=new qQ(a.c,a.a.b,a.b,a.priority,a.type,a.g,a.f);this.f||(a.type=1);a=this.b.a(a);for(var c=0;c<a.length;++c)b[c]=BU(a[c],b[c]);return b}; +function BU(a,b){var c=new FM;if("success"==a.getState())return LM(b,function(){"error"==b.getState()?KM(c):"success"==b.getState()&&HM(c,AU(b,a))}),c;LM(a,function(){"pending"==c.getState()&&("error"==a.getState()?KM(c):"success"==b.getState()&&HM(c,AU(b,a)))});LM(b,function(){"pending"==c.getState()&&("error"==b.getState()?KM(c):"success"==a.getState()&&HM(c,AU(b,a)))});LM(c,function(){JM(c)&&(b.cancel(),a.cancel())});return c};function CU(a,b){this.c=a;this.b=b}CU.prototype.a=function(a){for(var b=this.b.a(a),c=0;c<b.length;++c){var d=b[c];if("error"!=d.getState()){var e=a.mb()[c];DU(e,d,this.c)}}return b};function DU(a,b,c){MM(b,function(b){b=b.N;if(a&&b&&b.aa()!=a.aa()){b=b.b;for(var d=a.b,f=a.ba().a,g=0;g<b.length;++g){var h=b[g];if(null!==h&&h!=d[g]){var k=c,l=a.Ha,m=d[g],n=Ds(f.a[g]);(k=k.a[n])&&k.a.i(l,m,h)}}}})};function EU(a,b){this.b=a;this.c=b}EU.prototype.a=function(a){if(2==a.type){var b=a.mb();var c=Array(b.length);for(var d=0;d<b.length;d++)c[d]=rU(this.b,b[d],a.priority)}else if(3==a.type)for(c=this.c.a(a),d=0;d<c.length;d++)c[d]=qU(this.b,c[d],a.priority);else c=this.c.a(a);return c};function FU(){this.a=this.c=this.f=100}FU.prototype.b=0;FU.prototype.reset=function(){this.a=this.c=this.f;this.b=0};FU.prototype.na=function(){return this.c};function GU(a){this.result=a;this.a=new FU;this.b=-1};function HU(a,b,c){this.g=a;this.j=b;this.i=c;this.c={};this.f={};this.h=.707+.707*Math.random();this.b=new BP} +HU.prototype.a=function(a){for(var b=a.mb(),c=[],d={},e=[],f=0;f<b.length;++f){var g=b[f];var h=g.aa();h=this.c[h]?this.c[h]:(h=this.f[h])&&h.b>E()?h.result:null;h?(c[f]=h,this.b.a++):B(d[g.aa()])?(h=new FM,KM(h,""),c[f]=h,this.b.a++):(h=this.g.b(g),h=new lS(h,g),h.priority=a.priority,e.push(h),d[g.aa()]=f)}0<e.length&&IU(this,e,d,a.priority,a.g,c);for(f=0;f<b.length;++f)c[f]||(a=b[f].aa(),h=new FM,this.c[a]=h,KM(h,""),c[f]=h,this.b.f++,this.b.c++);return c}; +function IU(a,b,c,d,e,f){var g=E(),h=d+1,k=a.g;a.i.ed(new JU(function(){k.c(b,h,e)}),d);for(var l=0;l<b.length;++l){var m=b[l];a.b.f++;var n=m.N,p=n.aa(),q=new FM;f[c[p]]=q;m.priority=d;KU(a,q,m.result,g);LU(a,n,q,m)}}function KU(a,b,c,d){var e=a.b;LM(b,function(a){JM(a)?(e.i++,c.cancel()):"error"==a.getState()?e.c++:(e.g++,e.b+=E()-d)})} +function LU(a,b,c,d){LM(d.result,function(){if("pending"==c.getState()){var a=b.aa();if("success"==d.result.getState())MU(this,b,c,d),delete this.f[a];else{var f=this.f[a];f||(this.f[a]=new GU(c),f=this.f[a]);if(6>f.a.b){a=f;f=E();var g=this.h,h=a.a.na();B(g)&&(h*=g);a.b=f+h;a=a.a;a.a=Math.min(6400,2*a.a);a.c=Math.min(6400,a.a+0);a.b++}else this.c[a]=f.result,delete this.f[a];KM(c,"")}}},a)} +function MU(a,b,c,d){var e=a.j.a(d);e?(LM(c,function(a){JM(a)&&e.cancel()}),LM(e,function(){if("pending"==c.getState()){var a=e.na();a?HM(c,a):JM(e)||(this.c[b.aa()]=c,KM(c))}},a)):(d=b.aa(),a.c[d]=c,KM(c,""))}function JU(a){this.a=a;this.b=void 0}F(JU,SS);function NU(a,b,c,d,e){this.l=a;this.b=b;this.i=c;this.j=d;this.g=D(this.m,this);this.c=!1;this.f=D(function(){this.c=!1},this);this.h=e.C} +NU.prototype.a=function(a){if((1==a.type||3==a.type)&&!this.c&&WG(this.b)){var b=this;this.j.Mb(new OU(function(){for(var c=a.c,d=a.a,e=new QE,f=d.a,g=0;g<f.a.length;++g){var h=f.a[g],k=b.b,l=Ds(h);k.a[l]&&(k=UE(e),He(k,h),l=b.b,h=Ds(h),(h=(h=l.a[h])?h.c:null)&&(k.data[2]=h))}e.data[3]=4;g=new lE(Ae(e,10));g.data[0]=2;g.data[1]=!0;g=TE(e);g.data[4]=b.h;d.h&&(g.data[1]=d.h);rS(d.g)&&(g.data[2]=d.g);g=c;for(c=[];0<g.length;){d=[];k=g[0];f=k.getZoom();k=[k];for(h=1;h<g.length;++h)l=g[h],f==l.getZoom()? +k.push(l):d.push(l);c.push(k);g=d}for(g=0;g<c.length;++g)if(h=bC(c[g])){f=256*h.oa;d=256*(h.Yc-h.oa+1);k=256*h.xc;h=256*(h.bd-h.xc+1);2048<d&&(f+=(d-2048)/2,d=2048);2048<h&&(k+=(h-2048)/2,h=2048);l=new IE(Ae(new EE(De(e,0)),2));var m=c[g][0].getZoom();l.data[2]=m;m=new ME(Ae(l,0));m.data[0]=f;m.data[1]=k;f=new ME(Ae(l,1));f.data[0]=d;f.data[1]=h}b.l.a(e,1,b.g).wait(b.f)}),0);this.c=!0}return this.i.a(a)}; +NU.prototype.m=function(a,b){if(b){for(var c={},d=Fe(a,1),e=0;e<d;++e){var f=mC(a,e);c[f.wa()]=f}a=Fe(b,0);for(e=0;e<a;++e){var g=new VT(Ee(b,0,e));if(f=c[ze(g,0)])a:{d=this.b;if(f)f=Ds(f);else{if(!xe(g,0))break a;f=d.b[ze(g,0)];if(!f)break a}if(f=d.a[f])f.a.j(g),f.b++}}}};function OU(a){this.a=a;this.b=void 0}F(OU,SS);function PU(a){this.h=a;this.c=[];this.f=[];this.b=[]}PU.prototype.a=function(a){a=this.h.a(a);for(var b=[],c=0;c<a.length;c++){var d=a[c],e=this.c.indexOf(d);0>e?(e=new DP,b.push(e),this.f.push(e),this.c.push(d),this.b.push(!1),d.wait(this.g,this)):(this.f[e].b++,b.push(this.f[e]))}return b};PU.prototype.g=function(a){a=this.c.indexOf(a);this.b[a]=!0;if(0==a)for(;this.b[0];){this.b.shift();a=this.c.shift();var b=this.f.shift();a.na()?HM(b,a.na()):a.getError()&&KM(b,a.getError())}};function QU(a,b){this.b=a;this.c=b}QU.prototype.a=function(a){for(var b=a.mb(),c=Array(b.length),d=[],e=[],f=fU(this.b.c,a.b,a.a),g=0;g<b.length;++g){var h=b[g];var k=this.b;var l=f,m=h,n=m.aa();(n=k.a[n])?(k.b.a++,n.b++,k=n):l?(l=gU(l,m))&&l.data?(k.b.a++,k=new FM,HM(k,l)):k=null:k=null;k?c[g]=k:(d.push(h.Ha),e.push(g))}if(d.length)for(a=rQ(a,d),d=this.c.a(a),g=0;g<d.length;++g)f=e[g],h=b[f],k=d[g],"pending"!=k.getState()?(RU(this.b,k,a.f),c[f]=k):c[f]=SU(this.b,h.aa(),k,a.f);return c}; +function TU(a,b){this.c=a;this.a={};this.b=b}function RU(a,b,c){b=b.na();if(!b)return!1;if(b.data&&b.N){var d=b.N.ba(),e=b.N.Ea();a=a.c;d=eC(e,d);a.a[d]||(a.a[d]=new kU(a.c,a.f,a.b,a.h));mU(a.a[d],b,c)}return!0}function SU(a,b,c,d){var e=new DP;e.wait(function(a){JM(a)&&c.cancel()});a.a[b]=e;c.wait(function(c){delete a.a[b];"pending"==e.getState()&&(RU(a,c,d)?HM(e,c.na()):KM(e,c.getError()))});return e};function UU(a,b){this.c=a;this.b=b}UU.prototype.a=function(a){var b=this.b.a(a),c=Ls(a.a.c);if(c&&(a=MQ(this.c,c,a.priority+1),"pending"==a.getState()))for(c=0;c<b.length;++c){var d=RM(b[c],a);d=NM(d,function(a){return a[0].na()});b[c]=d}return b};function VU(){this.a=new Float32Array(6)}VU.prototype.set=function(a,b,c,d,e,f){this.a[0]=a;this.a[1]=b;this.a[2]=c;this.a[3]=d;this.a[4]=e;this.a[5]=f}; +function WU(a,b,c,d,e){var f=a.a[0],g=a.a[1],h=a.a[2],k=a.a[3],l=a.a[4],m=a.a[5];k<g&&(f=h,h=a.a[0],g=k,k=a.a[1]);m<k&&(l=h,h=a.a[4],m=k,k=a.a[5],k<g&&(h=f,f=a.a[4],k=g,g=a.a[5]));if(m<=b)g<b&&d.push(a);else if(g>=b)e.push(a);else if(a=f+(b-g)/(m-g)*(l-f),k==b){var n=c.get();n.set(f,g,h,k,a,b);d.push(n);n=c.get();n.set(h,k,a,b,l,m);e.push(n)}else if(k<b){var p=h+(b-k)/(m-k)*(l-h);XU(f,g,a,b,p,b,h,k,c,d);n=c.get();n.set(a,b,p,b,l,m);e.push(n)}else p=f+(b-g)/(k-g)*(h-f),n=c.get(),n.set(f,g,a,b,p,b), +d.push(n),XU(a,b,l,m,h,k,p,b,c,e)}function XU(a,b,c,d,e,f,g,h,k,l){if((e-a)*(e-a)+(f-b)*(f-b)<(g-c)*(g-c)+(h-d)*(h-d)){var m=k.get();m.set(a,b,c,d,e,f);l.push(m);m=k.get();m.set(a,b,e,f,g,h)}else m=k.get(),m.set(a,b,c,d,g,h),l.push(m),m=k.get(),m.set(c,d,e,f,g,h);l.push(m)}function YU(){this.hb=new Float32Array(4)}YU.prototype.set=function(a,b,c,d){b<d?(this.hb[0]=a,this.hb[1]=b,this.hb[2]=c,this.hb[3]=d):(this.hb[2]=a,this.hb[3]=b,this.hb[0]=c,this.hb[1]=d)};function ZU(a){this.b=a;this.a=Array(6)}ZU.prototype.mb=function(a,b){var c=this.a[b];c||(c=this.a[b]={});var d=Qs(a);if(a.f){var e=a.a;for(var f=a.f,g=Array(e.a.length),h=0;h<e.a.length;++h){var k=e.a[h],l=e.b[h];l||(l=e.b[h]=Ds(k));k=f.a[l];g[h]=k?k.b:null}e=g}else e=[];f=null;if(h=c[d])if(g=h.wf,e.length==g.length)for(f=h.uf,h=0;h<g.length;++h)if(e[h]!=g[h]){f=null;break}if(f)return f;g=this.b.length;f=Array(g);for(h=0;h<g;++h)f[h]=new dC(this.b[h],b,a);c[d]={wf:e,uf:f};return f};function $U(a,b){this.a=a;this.b=b;this.c=new ZU(a)}function aV(a,b){var c=a.b,d=b.b;if(c.bottom!=d.bottom||c.top!=d.top||c.zoom!=d.zoom)return!1;b=b.a;if(a.a.length!=b.length)return!1;for(c=0;c<a.a.length;++c){d=a.a[c];var e=b[c];if(!e||d.getZoom()!=e.getZoom()||d.b!=e.b||d.a!=e.a)return!1}return!0}$U.prototype.mb=function(a,b){return this.c.mb(a,b)};function bV(a){this.a=a}function cV(a,b){if(!b)return!1;b=b.a;if(a.a.length!=b.length)return!1;for(var c=0;c<a.a.length;++c)if(!aV(a.a[c],b[c]))return!1;return!0};function dV(a){this.c=new $J(YU);this.a=new $J(VU);this.h=new SF;this.f=new SF;this.b=new bV([]);this.g=a.ja} +function eV(a,b,c){var d=b.c,e=.02*b.a,f=[],g=0,h=b.a,k=Math.floor(pQ(a,b,c)+1E-6);if(b.b){var l=b.b,m=b.g;if(-.7854<=l&&.7854>=l&&1.0472>=m)k=Math.floor(fV(a,b,c,0)+1E-6)-(m<.1828/l?0:1);else{for(c=k;0<=c&&g<h;){var n=Math.round(gV(c,k,h,b));(0==g||n-g>=e)&&f.push(new MP(g,n,c));g=n;--c}var p=c+1}}f.length?n===h&&(f[f.length-1].top=h,f[f.length-1].zoom=p):f.push(new MP(0,h,k));e=[];for(g=0;g<f.length;++g){n=a;var q=d;h=f[g];var t=b;k=1<<h.zoom;var v=new vN;m=new eo;p=t.a-h.top;var u=t.a-h.bottom; +hV(t,0,p,k,k,v,m);var w=m.x;c=m.y;hV(t,q,p,k,k,v,m);var y=m.x;p=m.y;hV(t,0,u,k,k,v,m);var A=m.x;l=m.y;hV(t,q,u,k,k,v,m);q=m.x;m=m.y;t=n.a.get();t.set(w,c,y,p,A,l);w=n.a.get();w.set(A,l,q,m,y,p);w=[t,w];y=[];for(A=0;2>A;++A)WU(w[A],k,n.a,y,[]);w=[];for(A=0;A<y.length;++A)WU(y[A],0,n.a,[],w);if(0==w.length)h=null;else if(y=c,y>p&&(y=p),y>l&&(y=l),y>m&&(y=m),c<p&&(c=p),c<l&&(c=l),c<m&&(c=m),y=Yn(y,0,k),c=Yn(c,0,k),k=iV(n,w,y,c,k),aK(n.a),0==k.length)h=null;else{n=Array(k.length>>1);for(c=0;c<k.length;c+= +2)n[c>>1]=new kC(k[c],k[c+1],h.zoom);h=new $U(n,h)}h&&e.push(h)}return new bV(e)}function hV(a,b,c,d,e,f,g){xN(a,b,c,f);a=e/(2*Math.PI);b=f.origin[2]/f.a[2];g.x=d/2+d/(2*Math.PI)*(f.origin[0]-f.a[0]*b);g.y=e/2-(f.origin[1]-f.a[1]*b)*a} +function iV(a,b,c,d,e){for(var f=[],g=0;g<b.length;++g){var h=b[g],k=a.c,l=f,m=k.get();m.set(h.a[0],h.a[1],h.a[2],h.a[3]);l.push(m);m=k.get();m.set(h.a[0],h.a[1],h.a[4],h.a[5]);l.push(m);m=k.get();m.set(h.a[2],h.a[3],h.a[4],h.a[5]);l.push(m)}if(0==f.length)return[];b=[];d=Math.floor(d-.0078125);for(c=Math.floor(c+.0078125);c<=d;++c){k=1E100;h=0;l=c+1;for(g=0;g<f.length;++g){m=f[g].hb[1];var n=f[g].hb[3];if(!(m>l||n<c)){var p=n-m;if(0!=p){var q=f[g].hb[0],t=f[g].hb[2];p=(t-q)/p;n>l&&(t=q+(l-m)*p); +m<c&&(q+=(c-m)*p);q<t?(q<k&&(k=q),t>h&&(h=t)):(t<k&&(k=t),q>h&&(h=q))}}}k=Math.floor(k+.0078125);h=Math.floor(h-.0078125);h-k>=e&&(k=0,h=Math.max(0,e-1));for(g=k;g<=h;g++)k=g%e,0>k&&(k+=e),b.push(k),b.push(c)}aK(a.c);return b}function pQ(a,b,c){var d=fV(a,b,c);a=fV(a,b,c,0);return d<a?a:d}function fV(a,b,c,d){var e=0;1<a.g&&(e=a.g-1);1>c&&(e=Math.log(1/c)/Math.LN2,e-=.5,e=0<e?e:0);a=Math.log(1/mQ(b,b.a,d)*(tN/1/256))/Math.LN2;a-=e;22<a&&(a=22);0>a&&(a=0);return a} +function gV(a,b,c,d){a=Math.floor(a)-.5;var e=1/Math.tan(d.g/2);var f=d.a;var g=d.b,h=e*Math.cos(g)/Math.sin(g);b=-Math.sqrt(2/f*d.f*e/(Math.pow(2,b-a)*mQ(d,c)))/Math.sin(g);a=h+b;h-=b;f=(1-(a<h?-1.01>a||1.01<a?h:a:-1.01>h||1.01<h?a:h))*f/2;return 0>f||isNaN(f)||Infinity==f?c:c-f};function jV(a,b){jG(b,3,kV);var c=kV,d=kV;d[0]=-c[0];d[1]=-c[1];d[2]=-c[2];d[3]=-c[3];for(c=0;3>c;c++){d=2*c;jG(b,c,lV);var e=a[d],f=e,g=kV,h=lV;f[0]=g[0]-h[0];f[1]=g[1]-h[1];f[2]=g[2]-h[2];f[3]=g[3]-h[3];fG(e,1/Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]),e);e=d=a[d+1];f=kV;g=lV;e[0]=f[0]+g[0];e[1]=f[1]+g[1];e[2]=f[2]+g[2];e[3]=f[3]+g[3];fG(d,1/Math.sqrt(d[0]*d[0]+d[1]*d[1]+d[2]*d[2]),d)}}var kV=eG(),lV=eG();function mV(){this.c=new SF;this.f=new SF;this.a=new bV([]);this.g=new hP;this.b=[eG(),eG(),eG(),eG(),eG(),eG()]}var nV=[WF(),WF(),WF(),WF()]; +function oV(a,b){var c=[];b=[b];for(var d={};b.length;){var e=b.shift();if(!d[e.aa()]){d[e.aa()]=!0;var f=e;for(var g=0;4>g;g++){zG(f.b+g%2,f.a+(g>>1),f.getZoom(),nV[g]);var h=nV[g];xG(h[0],2*Math.atan(Math.exp(h[1]))-Math.PI/2,6371010*h[2],nV[g])}f=nV;a:{g=a.b;h=0;b:for(;6>h;++h){for(var k=0;k<f.length;k++){var l=f[k];if(0==(63&1<<h)||0>=cG(g[h],l)+g[h][3])continue b}f=!1;break a}f=!0}if(f){c.push(e);if(100<c.length)break;f=b;g=Math.pow(2,e.getZoom());h=(e.b+1)%g;f.push(new kC((e.b+g-1)%g,e.a,e.getZoom())); +f.push(new kC(h,e.a,e.getZoom()));if(0==e.a){if(256>g)for(h=0;h<g;h++)f.push(new kC(h,e.a,e.getZoom()))}else f.push(new kC(e.b,e.a-1,e.getZoom()));if(e.a==g-1){if(256>g)for(h=0;h<g;h++)f.push(new kC(h,e.a,e.getZoom()))}else f.push(new kC(e.b,e.a+1,e.getZoom()))}}}return c}function oQ(a){return Math.max(3,Math.log(a.a/256/(2*a.f*Math.tan(a.g/2))*2*Math.PI)/Math.LN2)};function pV(a){this.a=new dV(a);this.b=new mV} +function tQ(a,b,c,d){if(d){c=a.b;jQ(b,c.f);a=!1;TF(c.c,c.f)||(jQ(b,c.c),a=!0);if(a){a=b.a;d=Math.floor(oQ(b)+1E-6);var e=gG(),f=gG();eP(b,e,f);b=gG();lG(f,b);f=WF();var g=WF();sG(b,f);jV(c.b,e);e=nV[0];bG(f,e);var h=c.b[5];h[0]=-e[0];h[1]=-e[1];h[2]=-e[2];h[3]=0;e=WF();e[2]=-1;mG(b,e,g);ZF(g,f,g);bG(g,g);b=new vN(f,g);kP(c.g,b.origin,b.a,e);b=Math.atan2(e[1],e[0])/Math.PI;f=Math.PI-Math.log(Math.tan(Math.PI/4+Math.asin(Math.min(.999,Math.max(-.999,e[2]/6371010)))/2));f=.5*f/Math.PI;f=Math.min(1,Math.max(0, +f));b=Math.floor((b+1)/2*Math.pow(2,d));f=Math.floor(f*Math.pow(2,d));b=Math.min(b,Math.pow(2,d)-1);f=Math.min(f,Math.pow(2,d)-1);d=new kC(b,f,d);for(b=oV(c,d);100<b.length;)d=new kC(d.b>>1,d.a>>1,d.getZoom()-1),b=oV(c,d);a=new $U(b,new MP(0,a,d.getZoom()));a=new bV([a]);c.a&&cV(c.a,a)||(c.a=a)}c=c.a}else a=a.a,d=jQ(b,a.h),f=!1,TF(a.f,d)||(jQ(b,a.f),f=!0),f&&(c=eV(a,b,c),a.b&&cV(a.b,c)||(a.b=c)),c=a.b;return c};function pH(a,b,c){rc.call(this);this.a=a;this.G=b;Vs(Ss.sc(),a.a);this.h=new or;pr(this.h,"");this.i=a.B;this.I=new NB(this.h,tS(a.v));this.oc=new OB(this.h,tS(a.v));Jb(this,this.oc);this.l=qV(this,b,c,this.oc.c);b=500;pb&&2==a.c&&(b=Math.min(b,250));this.c=new oU(b,this.i);this.D=new TU(this.c,this.l.b);this.f=this.i?new jU(this.c,!1):new dU(this.c,!1);this.H=0;this.B=a.viewport||new pV(a);this.b=[];this.j=[];this.g=a.H;this.J=a.m&&this.g?rV(this,c):null;this.C=a.W;this.v=a.m;this.K=[];this.m=null; +this.A=new IQ(this.a,c,this.oc);var d=this;this.Pf=new eS(this.A,function(){sV(d,!0)});a=new no(this);Jb(this,a);a.cb(this.f,"ViewportReady",this.dispatchEvent);a.cb(this.f,"ViewportLoaded",this.dispatchEvent);a.cb(this.f,"ViewportMissingData",this.dispatchEvent);a.cb(this.c,"DataEvent",this.dispatchEvent)}F(pH,rc);pH.prototype.s=function(){return this.H}; +function qV(a,b,c,d){d=new IT(a.a,c,b,d);var e=new mS(c,1,new vS(a.a.U),a.a.V),f=a.a.j,g=a.a;if(!g.A){var h=new QE,k=UE(h);k.data[1]="shading";k.data[0]=5;k=UE(h);k.data[1]="contours";k.data[0]=6;UE(h);h.data[3]=0;(new OD(Ae(h,4))).data[5]=!0;(new OD(Ae(h,4))).data[4]=g.la;k=TE(h);k.data[4]=g.C;(new Sn(De(k,11))).data[0]=67;(new Sn(De(k,11))).data[0]=63;(new Sn(De(k,11))).data[0]=3;g.A=h}c=new mS(c,2,new uS(f,g.A),a.a.a);return new HU(new jS([d,e,c]),new OT(b,[new ST(b,Yn(a.a.la,1,2),a.h,a.I,a.a.S? +a.a.f:void 0),new QT(b)]),b)}function rV(a,b){var c=tS(a.a.K);a=new YT(b,c,a.a.a);return new ZT(new TT(a))}function sV(a,b){a.H++;a.m&&a.m(b)}function tV(a,b){var c=new pU(a.c,b),d=a.l;a.v&&a.g&&(d=new CU(a.g,d));var e=d;a.v&&a.i&&(e=new wU(e,a.G,Yn(a.a.la,1,2)));a.v&&a.J&&a.g&&(e=new NU(a.J,a.g,e,a.G,a.a));a.C&&(e=new PU(e));e=new UU(a.A,e);a.i&&(b=b.Je(),d=new QU(a.D,d),a.C&&(d=new PU(d)),b&&(d=new UU(a.A,d),d=new EU(c,d)),e=new zU(b,e,d));e=new QU(a.D,e);return e=new EU(c,e)} +pH.prototype.Xc=function(a,b,c){b=tV(this,b);var d=this;a=new sU(a,b,this.B,this.f,function(a){for(var b=0;b<a.length;++b)MM(a[b],function(){sV(d,!1)},d)},c,[this.l]);Jb(this,a);this.K.push(a);return a}; +pH.prototype.getData=function(a,b,c,d,e,f,g,h){var k=tQ(this.B,a,b,f),l=this.f,m=!!h,n=[],p=[];h=[];k=k.a;for(var q=0;q<d.length;++q){for(var t=[],v=0;v<k.length;++v){var u=k[v],w=u.mb(c,d[q]);w=eU(l,c,d[q],w,e,m,n,p,g);t.push(new cS(w,u.b))}h.push(new dS(t))}0==n.length&&(l.dispatchEvent(new aU(l)),0==p.length&&l.dispatchEvent(new cU(l)));0==n.length&&0==p.length||l.dispatchEvent(new bU(l,n.concat(p)));c=[];for(d=0;d<this.b.length;++d)if(e=this.b[d]){n="cat"+String(2+d);p=tQ(this.B,a,b,f);l=g;m= +new On;m.data[1]=n;m.data[0]=2;n=p.a;p=n.length;k=[];for(q=0;q<p;++q){t=[];v=n[q].a;u=m;w=l;var y=[],A=Array(v.length);e.mb(v,A);for(var z=0;z<A.length;++z){var C=A[z];if(C){var I=fU(this.c,C.Ea(),C.ba());(I=I?gU(I,C):null)&&I.data&&I.a&&(C=uV(C,u),C=new pO(C,I.data),C.a=I.a,I=!0,w&&(I=vV(C,w)),I&&y.push(C))}}u=y;0<u.length&&(t=u.concat(t));u=l;w=[];y=Array(v.length);A=new Os(void 0,new Es([m]));for(z=0;z<v.length;++z)if(C=y[z])I=new dC(v[z],4,A),C=new RR(C,this.h,void 0,this.I),I=new pO(I,C),C=!0, +u&&(C=vV(I,u)),C&&w.push(I);v=w;0<v.length&&(t=v.concat(t));t.length&&k.push(new cS(t,n[q].b))}c.push(new dS(k))}return h.concat(c)};function uV(a,b){var c=a.ba(),d=new Es(c.a.a.slice());d.a.push(b);d.b.push(void 0);return new dC(a.Ha,a.a,new Os(c.c,d,c.h,c.g,c.f||void 0,c.b||void 0))}function vV(a,b){return b.fb(a)?!0:"success"==b.ic(a,2,a.a.s).getState()}function zP(a,b){a.m=b} +pH.prototype.X=function(){for(var a=0;a<this.b.length;++a){var b=this.b[a];if(b)a:for(var c=0;c<this.b.length;++c)if(this.b[c]===b){this.b[c]=null;this.j[c]&&mc(this.j[c]);this.j[c]=null;sV(this,!0);break a}}pH.R.X.call(this)};NG(1,new function(){});NG(2,new function(){});var wV=[],xV=[];function yV(a,b){var c=a.wa();if(void 0==wV[c]){wV[c]=[];xV[c]=[];var d=new no;d.cc(a.j,"webglcontextlost",function(){wV[c]=null;xV[c]=null});Kb(a,function(){wV[c]=null;xV[c]=null;d.$()})}a=wV[c].indexOf(b);-1!=a?a=xV[c][a]:(a=new b,wV[c].push(b),xV[c].push(a));return a} +function zV(a,b,c,d){var e=a.createShader(35632);a.shaderSource(e,c);a.compileShader(e);c=a.createShader(35633);a.shaderSource(c,b);a.compileShader(c);b=a.createProgram();a.attachShader(b,c);a.attachShader(b,e);for(e=0;e<d.length;e++)a.bindAttribLocation(b,e,d[e]);a.linkProgram(b);return b};function AV(){this.o=this.b=this.ea=this.C=this.m=this.s=this.v=this.i=this.h=this.g=this.f=this.c=this.D=this.j=this.l=this.G=this.H=this.u=this.A=this.B=null;this.I={}}var BV="#define _b 8\n#define _c 8000\n#define _d "+QB+"\n#define _e 2\n#define _f 16\n#define _g 8\n#define _h vec4(0., 0., 0., 0.2)\n#define _i 2\n#define _j 9\n#define _k 6\n#define _l 3\n#define _m 0\n#define _n 1\n#define _o 2\n#define _p 4\n#define _q 5\n#define _r 12\n#define _s 0\n#define _t 8\n#define _u 2\n#define _v 1\n#define _w 22\n\n"; +AV.prototype.a=function(a,b){b="#define _a "+b.f+"\n";var c=this.I[b];c||(c=zV(a,BV+b+"precision highp float;uniform vec4 d,f,j;uniform sampler2D e,g;vec2 M(vec2 A,float B){float C=float(_r);A.y=C*A.y+B;return (A+.5)*d.zw;}vec2 N(vec4 A){return vec2(A.g+A.b*256.,A.a);}vec2 O(vec2 u){vec4 A=texture2D(g,(floor(u*65535.+.5)+.5)*f.zw);A=floor(A*255.+.5);return N(A);}\n#if _a==1\nuniform float h;varying vec3 i;\n#endif\nuniform vec3 k,l;uniform mat4 m;uniform float o,s;\n#if _a==1\nuniform mat4 p;vec3 P(vec3 A){const float B=6371010.;float C,D,E,F,G,H,I,J,K,L;C=A.x;D=exp(A.y);E=D*D;F=2.*D/(1.+E);G=(E-1.)/(1.+E);H=A.z*B*F;I=H+B;J=I*F*cos(C);K=I*F*sin(C);L=I*G;return vec3(J,K,L);}vec4 Q(vec3 A){vec4 B,D;B=m*vec4(A,1);vec3 t,C;t=A;t/=o;t+=k+l;t.xy-=.5;t.y=-t.y;t*=3.141592653589793*2.;C=P(t);D=p*vec4(C,1);D/=D.w;B/=B.w;return mix(B,D,h);}vec3 R(vec3 t){t/=o;t+=k+l;t.xy-=.5;t.y=-t.y;t*=3.141592653589793*2.;vec3 A=mat3(p)*P(t);return normalize(A);}\n#else\nvec4 Q(vec3 A){return m*vec4(A,1);}\n#endif\nvec3 S(vec3 A,vec3 B){vec3 t=A-k+(B-l);return t*o;}vec3 T(vec2 A,vec2 B,vec2 C){vec3 D,E;D=vec3(A.x,B.x,C.x)*65535.+.5;\n#if _a==1\nD-=fract(D);\n#else\nD=floor(D);\n#endif\nD=D/65536.;D=(fract(D+.5)-.5)*4.;E=vec3(A.y,B.y,C.y)*65535.;E/=1073741824.;return S(D,E);}float U(vec4 A){float B,C;B=1./float(_w+1);C=1.-B-j.z*B;return A.z*B+A.w*C;}void V(vec3 A){\n#if _a==1\ni=R(A);\n#endif\n}precision highp float;varying vec4 r;attribute vec4 t;attribute vec2 u;attribute float v;uniform vec2 w;void main(){vec3 A=T(t.yx,t.wz,vec2(0));V(A);gl_Position=Q(A);gl_Position.xy+=w*gl_Position.w;gl_Position.z=gl_Position.w*v;vec2 B,C;B=O(u);C=M(B,float(_l));r=texture2D(e,C);gl_Position.z=U(gl_Position);gl_Position.xy*=sign(r.a*abs(s-floor(r.a)));}", +BV+b+"precision highp float;precision highp float;\n#if _a==1\nuniform float h;varying vec3 i;\n#endif\nfloat C(){\n#if _a==1\nfloat x,A;x=dot(i,vec3(-1.,1,-1.));A=clamp((x-.5)/4.+1.,.5,1.);return mix(1.,A,h);\n#else\nreturn 1.;\n#endif\n}precision highp float;varying vec4 r;void main(){float x=C();gl_FragColor=vec4(r.rgb*x,r.a);}",["t","u","v"]),this.I[b]=c);this.b=c}; +AV.prototype.bind=function(a,b){this.a(a,b);if(this.o!=this.b){var c=this.b,d=function(b){return a.getUniformLocation(c,b)};this.B=d("a");this.A=d("b");this.u=d("c");this.H=d("d");this.G=d("e");this.l=d("f");this.j=d("g");this.D=d("h");this.c=d("j");this.f=d("k");this.g=d("l");this.h=d("m");this.i=d("n");this.v=d("o");this.s=d("p");this.m=d("q");this.C=d("s");this.ea=d("w");this.o=this.b}a.useProgram(this.o);this.B&&a.uniform4fv(this.B,b.s.value);this.A&&a.uniform4fv(this.A,b.o.value);this.u&&a.uniform1f(this.u, +b.b.value);this.H&&a.uniform4fv(this.H,b.B.value);this.G&&a.uniform1i(this.G,b.A.value);this.l&&a.uniform4fv(this.l,b.v.value);this.j&&a.uniform1i(this.j,b.u.value);this.D&&a.uniform1f(this.D,b.c.value);this.c&&a.uniform4fv(this.c,b.C.value);this.f&&a.uniform3fv(this.f,b.g.value);this.g&&a.uniform3fv(this.g,b.h.value);this.h&&a.uniformMatrix4fv(this.h,!1,b.i.value);this.i&&a.uniform1f(this.i,b.j.value);this.v&&a.uniform1f(this.v,b.m.value);this.s&&a.uniformMatrix4fv(this.s,!1,b.a.value);this.m&&a.uniform1i(this.m, +b.l.value);this.C&&a.uniform1f(this.C,b.La.value);this.ea&&a.uniform2fv(this.ea,b.ea.value)};var CV={5120:1,5121:1,5122:2,5123:2,5124:4,5125:4,5126:4};function DV(a,b,c,d,e){this.index=a;this.arity=b;this.a=c;this.b=d;this.c=e}function EV(a,b){for(var c=[],d=0,e=[],f=0,g=0;g<b.length;g++){var h=b[g][0],k=b[g][1],l=2<b[g].length?b[g][2]:!1,m=h*CV[k];h=new DV(g,h,k,5126!=k,l?f:d);m=m+3&-4;l?(e.push(h),f+=m):(c.push(h),d+=m)}this.c=c;this.b=a;this.a=d;this.f=d/4;this.h=d*a/4;this.g=e;this.i=f} +function FV(a,b){if(b.g.length){for(var c=mq(a),d=0;d<b.c.length;d++){var e=b.c[d];a.enableVertexAttribArray(e.index);c.vertexAttribDivisorANGLE(e.index,1)}for(d=0;d<b.g.length;d++)e=b.g[d],a.enableVertexAttribArray(e.index),c.vertexAttribDivisorANGLE(e.index,0)}else for(d=0;d<b.c.length;d++)e=b.c[d],a.enableVertexAttribArray(e.index)} +function GV(a,b){if(b.g.length){for(var c=mq(a),d=0;d<b.c.length;d++){var e=b.c[d];a.disableVertexAttribArray(e.index);c.vertexAttribDivisorANGLE(e.index,0)}for(d=0;d<b.g.length;d++)e=b.g[d],a.disableVertexAttribArray(e.index),c.vertexAttribDivisorANGLE(e.index,0)}else for(d=0;d<b.c.length;d++)e=b.c[d],a.disableVertexAttribArray(e.index)}function HV(a,b){var c=a.createBuffer(),d=a.a.b;B(d)||(d=null);a.a.Ua(c);a.bufferData(34962,new Float32Array(b),35044);a.a.Ua(d);return c} +function IV(a,b,c,d,e,f){var g=[];b=(b-a)/c;e=(e-d)/f;for(var h=0;h<f;h++)for(var k=d+e*h,l=d+e*(h+1),m=0;m<c;m++){var n=a+b*m,p=a+b*(m+1);g.push(n);g.push(k);g.push(n);g.push(l);g.push(p);g.push(k);g.push(p);g.push(k);g.push(n);g.push(l);g.push(p);g.push(l)}return g}function JV(a,b,c,d,e,f,g){b=IV(b,c,d,e,f,g);return{buffer:HV(a,b),size:b.length/2}} +function KV(a,b,c,d){var e=!1;a.a.b!=b&&(a.a.Ua(b),e=!0);if(e||B(d))for(b=B(d)?d:0,d=0;d<c.c.length;d++)e=c.c[d],a.vertexAttribPointer(e.index,e.arity,e.a,e.b,c.a,e.c+b)}function LV(a,b,c){a.a.b!=b&&a.a.Ua(b);for(b=0;b<c.g.length;b++){var d=c.g[b];a.vertexAttribPointer(d.index,d.arity,d.a,d.b,c.i,d.c)}}function MV(a,b,c){c.a!=a.a.b&&KV(a,c.a,b);a.drawArrays(4,c.b,c.c)}function NV(a,b,c,d){c&&MV(a,b,c);d&&MV(a,b,d)} +function OV(a,b,c,d){var e=mq(a);c&&(KV(a,c.a,b,c.b*b.a),e.drawArraysInstancedANGLE(4,0,6,c.c));d&&(KV(a,d.a,b,d.b*b.a),e.drawArraysInstancedANGLE(4,0,6,d.c))}function PV(a,b,c){c=B(c)?c:b.length;var d=lr(a,4*c);c<b.length&&(b=b.subarray(0,c));nr(a,d,b);return d} +function QV(a,b,c,d,e,f){var g=b.l,h=b.o,k=h.left,l=b.j-h.right,m=h.bottom;h=b.i-h.top;f>h&&(f=h);e>l&&(e=l);d<m&&(d=m);c<k&&(c=k);c-=.01;e+=.01;f+=.01;d-=.01;e<c&&(e=c);f<d&&(f=d);c=c*g+b.a.x;f=f*g+b.a.y;e=e*g+b.a.x;d=d*g+b.a.y;c=c+.5|0;d=d+.5|0;a.scissor(c,d,(e+.5|0)-c,(f+.5|0)-d)}function RV(a,b){QV(a,b,0,0,b.j,b.i)} +function SV(a,b,c,d,e,f){if(b.B)a.stencilFunc(514,c,255);else{c=d-b.H;var g=e+256*f-b.I;d=d+256*f-b.H;e-=b.I;c*=b.m;d*=b.m;g*=b.m;e*=b.m;c+=b.j/2;d+=b.j/2;g=-g+b.i/2;e=-e+b.i/2;QV(a,b,c,g,d,e)}} +function TV(a,b,c,d,e,f,g){switch(c){case 1:a.colorMask(!1,!1,!1,!1);a.enable(3042);break;case 2:a.colorMask(!0,!0,!0,!0);a.disable(3042);break;case 3:a.colorMask(!0,!0,!0,!0);a.enable(3042);a.blendFuncSeparate(770,771,1,771);a.blendEquation(32774);break;case 4:a.colorMask(!0,!0,!0,!0);a.enable(3042);a.blendFuncSeparate(1,771,1,771);a.blendEquation(32774);break;case 5:a.colorMask(!0,!0,!0,!0),a.enable(3042),a.blendFuncSeparate(770,0,1,0),a.blendEquation(32774)}switch(d){case 1:a.depthMask(!1);a.disable(2929); +break;case 2:a.depthMask(!0);a.disable(2929);break;case 3:a.depthMask(!0);a.enable(2929);a.depthFunc(515);break;case 4:a.depthMask(!0),a.enable(2929),a.depthFunc(513)}2==e&&0==b.B&&(e=1);switch(e){case 1:a.disable(2960);a.stencilOp(7680,7680,7680);break;case 2:a.enable(2960);a.stencilOp(7680,7680,7680);break;case 3:a.enable(2960);a.stencilOp(7680,7681,7681);break;case 4:a.enable(2960),a.stencilFunc(514,0,4294967295),a.stencilOp(7680,7680,7682)}switch(f){case 2:a.enable(3089);RV(a,b);break;case 1:a.disable(3089)}switch(g){case 1:a.disable(2884); +break;case 2:a.enable(2884);a.cullFace(1029);break;case 3:a.enable(2884),a.cullFace(1028)}}function UV(a,b,c){c&&(c&16384&&(a.colorMask(!0,!0,!0,!0),b=b.clearColor,a.clearColor(b[0],b[1],b[2],b[3])),c&256&&(a.depthMask(!0),a.clearDepth(1)),c&1024&&a.clearStencil(0),a.disable(3089),a.clear(c))};function VV(a,b,c){var d=a.a,e=a.data;if(UM(e))return!1;22<c&&(c=22);a=Math.floor(c);c=c!=a;var f=b.c,g=c?a+.5:a;if(f==d.Wa&&g==d.Za)return d.Ja;var h=!1;e=e.b.a[2];for(var k=0;k<e.length;k++){var l=e[k].ka(),m=GK(d.f,l);l=WV(RA(b.a,m),c,a);if(2==l){h=!0;break}if(ZB(b)){m=WV(RA(b.b,m),c,a);if(2==m){h=!0;break}if((0==m||0==l)&&m!=l){h=!0;break}}}d.Ja=h;d.Wa=f;d.Za=g;return d.Ja}function WV(a,b,c){return a.D?0<(aA(a,c)>>24&255)%255||b&&0<(aA(a,c+1)>>24&255)%255?2:1:0};function XV(a,b){this.u=a;this.v=b;this.D=yV(a,AV);this.a=new EV(3,[[4,5123],[2,5123],[2,5123]]);this.A=new ir(this.u,this.a.a,this.a.b,65536);this.C=new sI(1,!0);this.B=new sI(1,!0);this.c=[];this.f=[];this.h=[];this.g=[];this.i=[];this.j=[];this.l=[];this.o=[];this.m=[];this.s=[]} +function YV(a,b,c,d){var e=a.u,f=a.v;if(d){var g=a.j;if(c){var h=a.o;c=a.s}else h=a.l,c=a.m}else g=a.c,c?(h=a.h,c=a.i):(h=a.f,c=a.g);if(g.length){TV(e,b,3,d?4:3,2,2,2);f.La.set(d?1:0);d=g;e=h;f=a.u;var k=a.v;h=a.D;g=a.a;FV(f,g);k.ea.set(b.Va.x,b.Va.y);var l=hq(f);h.bind(l,k);for(k=0;k<e.length;k++){var m=d[k],n=e[k]||[],p=c[k]||[];l.uniform4f(h.c,m.g,m.h,m.m,m.b);SV(f,b,m.Z,m.g,m.h,m.b);for(m=0;m<n.length;m++)MV(f,g,n[m]);for(m=0;m<p.length;m++)MV(f,g,p[m])}GV(f,a.a);iq(f)}} +XV.prototype.b=function(a,b){var c=a.a,d=a.data,e=d.a;if(c.ga||!e||!Gy(e)||!ly(Hy(e)))return 2;var f=rI(d.getZoom(),b),g=this.C;b=this.B;g.reset(c.g,c.h,c.b,d.c);b.reset(c.g,c.h,c.b,d.c);g.i=f;b.i=f;d=d.b.a[2];for(var h=a.a.c,k=a.data.b.a[5],l=a=0;l<k.length;l++){var m=k[l].za;m>a&&(a=m)}e=Hy(e).a;for(k=0;k<e.length;k++)if(l=e[k],(m=null==l.c?!1:l.c)||null!=l.a){var n=d[k].ka(),p=d[k].za,q=l.getExtension(177034656);f&&q&&(null==q.a?0:q.a)||(q=p<a?g:b,n=ZV(h,n),q.o=oI(n.x,n.y),q.m=oI(65535-p,0),m? +(uI(q),wI(q,0,0),wI(q,4096,0),wI(q,4096,4096),wI(q,0,4096),vI(q,0,0)):(l=ux(l),LI(l,q,f)))}if(0!=g.b||0!=g.a)f=PV(this.A,g.h.subarray(0,g.b)),jO(c.a,f),c.ga=f.a;if(0!=b.b||0!=b.a)f=PV(this.A,b.h.subarray(0,b.b)),jO(c.a,f),c.Ba=f.a;return 2};function $V(){this.D=this.c=this.h=this.g=this.m=this.f=this.i=this.j=this.l=this.ea=this.C=this.G=this.I=this.v=this.u=this.s=this.o=this.b=this.L=this.A=this.B=this.M=this.O=this.H=this.J=this.K=null;this.P={}}var aW="#define _b 8\n#define _c 8000\n#define _d "+QB+"\n#define _e 2\n#define _f 16\n#define _g 8\n#define _h vec4(0., 0., 0., 0.2)\n#define _i 2\n#define _j 9\n#define _k 6\n#define _l 3\n#define _m 0\n#define _n 1\n#define _o 2\n#define _p 4\n#define _q 5\n#define _r 12\n#define _s 0\n#define _t 8\n#define _u 2\n#define _v 1\n#define _w 22\n\n"; +$V.prototype.a=function(a,b){b="#define _a "+b.f+"\n";var c=this.P[b];c||(c=zV(a,aW+b+"precision highp float;uniform vec4 d,f,j;uniform sampler2D e,g;vec2 S(vec2 G,float H){float I=float(_r);G.y=I*G.y+H;return (G+.5)*d.zw;}vec2 T(vec4 G){return vec2(G.g+G.b*256.,G.a);}vec2 U(vec2 u){vec4 G=texture2D(g,(floor(u*65535.+.5)+.5)*f.zw);G=floor(G*255.+.5);return T(G);}\n#if _a==1\nuniform float h;varying vec3 i;\n#endif\nuniform vec3 k,l,w,x,A,B,C,D;uniform mat4 m;uniform float o,E;\n#if _a==1\nuniform mat4 p;vec3 V(vec3 G){const float H=6371010.;float I,J,K,L,M,N,O,P,Q,R;I=G.x;J=exp(G.y);K=J*J;L=2.*J/(1.+K);M=(K-1.)/(1.+K);N=G.z*H*L;O=N+H;P=O*L*cos(I);Q=O*L*sin(I);R=O*M;return vec3(P,Q,R);}vec4 W(vec3 G){vec4 H,K;H=m*vec4(G,1);vec3 I,J;I=G;I/=o;I+=k+l;I.xy-=.5;I.y=-I.y;I*=3.141592653589793*2.;J=V(I);K=p*vec4(J,1);K/=K.w;H/=H.w;return mix(H,K,h);}\n#else\nvec4 W(vec3 G){return m*vec4(G,1);}\n#endif\nvec3 X(vec3 G,vec3 H){vec3 I=G-k+(H-l);return I*o;}vec3 Y(vec3 G){vec3 H,I;H=vec3(j.x,j.y,0);I=G*j.w;I.xy*=1./float(_f);return X(H,I);}vec4 Z(vec3 G){vec3 H=Y(G);return W(H);}varying vec4 r;attribute vec4 s;attribute vec4 t;attribute vec2 u;uniform vec2 v;vec4 aa(vec4 G,vec3 H,float I){float J,L,N;J=mix(E,1.,I);vec3 K,M,O,P;K=mix(A,x,(H.z+1.)*.5)*J;L=clamp(dot(H,C),0.,1.);M=w*L*J;N=clamp(dot(H,D),0.,1.);O=B*N;P=K+M-K*M;P=P+O-P*O;G.rgb*=P;return G;}void main(){vec3 G,L;G=floor(s.xyz*32767.+.5);G.z/=float(_f);gl_Position=Z(G);vec4 H,K;H=Z(vec3(G.xy,0));float I=clamp((H.z+H.w)/(H.w-gl_Position.w+H.z-gl_Position.z+.001),0.,1.);gl_Position=Z(vec3(G.xy,I*G.z));gl_Position.xy+=v*gl_Position.w;vec2 J=U(u);K=texture2D(e,S(J,float(_l)));L=normalize(t.xyz-127./254.);r=aa(K,L,clamp(s.z/s.w,0.,1.));}", +aW+b+"precision highp float;precision highp float;\n#if _a==1\nvarying vec3 i;\n#endif\nvarying vec4 r;void main(){gl_FragColor=r;}",["s","t","u"]),this.P[b]=c);this.c=c}; +$V.prototype.bind=function(a,b){this.a(a,b);if(this.D!=this.c){var c=this.c,d=function(b){return a.getUniformLocation(c,b)};this.K=d("a");this.J=d("b");this.H=d("c");this.O=d("d");this.M=d("e");this.B=d("f");this.A=d("g");this.L=d("h");this.b=d("j");this.o=d("k");this.s=d("l");this.u=d("m");this.v=d("n");this.I=d("o");this.G=d("p");this.C=d("q");this.ea=d("v");this.l=d("w");this.j=d("x");this.i=d("A");this.f=d("B");this.m=d("C");this.g=d("D");this.h=d("E");this.D=this.c}a.useProgram(this.D);this.K&& +a.uniform4fv(this.K,b.s.value);this.J&&a.uniform4fv(this.J,b.o.value);this.H&&a.uniform1f(this.H,b.b.value);this.O&&a.uniform4fv(this.O,b.B.value);this.M&&a.uniform1i(this.M,b.A.value);this.B&&a.uniform4fv(this.B,b.v.value);this.A&&a.uniform1i(this.A,b.u.value);this.L&&a.uniform1f(this.L,b.c.value);this.b&&a.uniform4fv(this.b,b.C.value);this.o&&a.uniform3fv(this.o,b.g.value);this.s&&a.uniform3fv(this.s,b.h.value);this.u&&a.uniformMatrix4fv(this.u,!1,b.i.value);this.v&&a.uniform1f(this.v,b.j.value); +this.I&&a.uniform1f(this.I,b.m.value);this.G&&a.uniformMatrix4fv(this.G,!1,b.a.value);this.C&&a.uniform1i(this.C,b.l.value);this.ea&&a.uniform2fv(this.ea,b.ea.value);this.l&&a.uniform3fv(this.l,b.ra.value);this.j&&a.uniform3fv(this.j,b.pa.value);this.i&&a.uniform3fv(this.i,b.ja.value);this.f&&a.uniform3fv(this.f,b.fa.value);this.m&&a.uniform3fv(this.m,b.va.value);this.g&&a.uniform3fv(this.g,b.ga.value);this.h&&a.uniform1f(this.h,b.ia.value)};function bW(){this.u=this.b=this.o=this.ea=this.s=this.m=this.v=this.B=this.i=this.h=this.g=this.f=this.c=this.G=this.j=this.l=this.H=this.I=this.A=this.C=this.D=null;this.J={}}var cW="#define _b 8\n#define _c 8000\n#define _d "+QB+"\n#define _e 2\n#define _f 16\n#define _g 8\n#define _h vec4(0., 0., 0., 0.2)\n#define _i 2\n#define _j 9\n#define _k 6\n#define _l 3\n#define _m 0\n#define _n 1\n#define _o 2\n#define _p 4\n#define _q 5\n#define _r 12\n#define _s 0\n#define _t 8\n#define _u 2\n#define _v 1\n#define _w 22\n\n"; +bW.prototype.a=function(a,b){b="#define _a "+b.f+"\n";var c=this.J[b];c||(c=zV(a,cW+b+"precision highp float;uniform vec4 d,f,j;uniform sampler2D e,g;vec2 M(vec2 A,float B){float C=float(_r);A.y=C*A.y+B;return (A+.5)*d.zw;}vec2 N(vec4 A){return vec2(A.g+A.b*256.,A.a);}vec2 O(vec2 u){vec4 A=texture2D(g,(floor(u*65535.+.5)+.5)*f.zw);A=floor(A*255.+.5);return N(A);}\n#if _a==1\nuniform float h;varying vec3 i;\n#endif\nuniform vec3 k,l;uniform mat4 m;uniform float o,r,w;\n#if _a==1\nuniform mat4 p;vec3 P(vec3 A){const float B=6371010.;float C,D,E,F,G,H,I,J,K,L;C=A.x;D=exp(A.y);E=D*D;F=2.*D/(1.+E);G=(E-1.)/(1.+E);H=A.z*B*F;I=H+B;J=I*F*cos(C);K=I*F*sin(C);L=I*G;return vec3(J,K,L);}vec4 Q(vec3 A){vec4 B,E;B=m*vec4(A,1);vec3 C,D;C=A;C/=o;C+=k+l;C.xy-=.5;C.y=-C.y;C*=3.141592653589793*2.;D=P(C);E=p*vec4(D,1);E/=E.w;B/=B.w;return mix(B,E,h);}\n#else\nvec4 Q(vec3 A){return m*vec4(A,1);}\n#endif\nvec3 R(vec3 A,vec3 B){vec3 C=A-k+(B-l);return C*o;}vec3 S(vec3 A){vec3 B,C;B=vec3(j.x,j.y,0);C=A*j.w;C.xy*=1./float(_f);return R(B,C);}vec4 T(vec3 A){vec3 B=S(A);return Q(B);}attribute vec4 s;attribute vec4 t;attribute vec2 u;uniform vec2 v;void main(){vec3 A,D;A=floor(s.xyz*32767.+.5);vec2 B,C,E;B=normalize(vec2(sin(w),cos(w)));C=max(0.,A.z)/tan(r)*B;C/=2.;D=vec3(A.xy+C,0);gl_Position=T(D);gl_Position.xy+=v*gl_Position.w;E=O(u);vec4 F=texture2D(e,M(E,float(_l)));gl_Position*=ceil(F.a);}", +cW+b+"precision highp float;precision highp float;\n#if _a==1\nvarying vec3 i;\n#endif\nvoid main(){gl_FragColor=vec4(0,.18,.33,.03);}",["s","t","u"]),this.J[b]=c);this.b=c}; +bW.prototype.bind=function(a,b){this.a(a,b);if(this.u!=this.b){var c=this.b,d=function(b){return a.getUniformLocation(c,b)};this.D=d("a");this.C=d("b");this.A=d("c");this.I=d("d");this.H=d("e");this.l=d("f");this.j=d("g");this.G=d("h");this.c=d("j");this.f=d("k");this.g=d("l");this.h=d("m");this.i=d("n");this.B=d("o");this.v=d("p");this.m=d("q");this.s=d("r");this.ea=d("v");this.o=d("w");this.u=this.b}a.useProgram(this.u);this.D&&a.uniform4fv(this.D,b.s.value);this.C&&a.uniform4fv(this.C,b.o.value); +this.A&&a.uniform1f(this.A,b.b.value);this.I&&a.uniform4fv(this.I,b.B.value);this.H&&a.uniform1i(this.H,b.A.value);this.l&&a.uniform4fv(this.l,b.v.value);this.j&&a.uniform1i(this.j,b.u.value);this.G&&a.uniform1f(this.G,b.c.value);this.c&&a.uniform4fv(this.c,b.C.value);this.f&&a.uniform3fv(this.f,b.g.value);this.g&&a.uniform3fv(this.g,b.h.value);this.h&&a.uniformMatrix4fv(this.h,!1,b.i.value);this.i&&a.uniform1f(this.i,b.j.value);this.B&&a.uniform1f(this.B,b.m.value);this.v&&a.uniformMatrix4fv(this.v, +!1,b.a.value);this.m&&a.uniform1i(this.m,b.l.value);this.s&&a.uniform1f(this.s,b.Ga.value);this.ea&&a.uniform2fv(this.ea,b.ea.value);this.o&&a.uniform1f(this.o,b.Da.value)};function dW(a,b){this.f=a;this.h=b;this.c=yV(a,$V);this.g=yV(a,bW);this.a=new EV(3,[[4,5122],[4,5121],[2,5123]]);this.i=new ir(a,this.a.a,this.a.b,void 0)} +function eW(a,b){a=a.h;var c=b.S;0>=c&&(c=1);var d=Math.PI/180,e=b.P*d;c*=d;var f=Math.sin(e),g=Math.cos(e),h=Math.sin(c),k=Math.cos(c);a.Da.set(e);a.Ga.set(c);a.va.set(-f*k,-g*k,h);a.ga.set(-Math.sin(e+150*d),-Math.cos(e+150*d),0);a.ra.set(1/h,1/h,.85/h);a.pa.set(.85,.85,1);a.ja.set(.9,.9,.85);a.fa.set(.25,.3,.35);a.ia.set(.9);a.ea.set(b.Va.x,b.Va.y)} +function fW(a){for(var b=0;b<a.length;b++)for(var c=a[b],d=0;d<c.a.length;d++)for(var e=c.a[d],f=0;f<e.a.length;++f){var g=e.a[f];if(g.a.L||g.b&&g.b.a.L)return!0}return!1} +function gW(a,b,c,d){for(var e=0;e<c.length;e++)for(var f=c[e],g=0;g<f.a.length;g++)for(var h=f.a[g],k=0;k<h.a.length;++k){var l=h.a[k];if(l){var m=a,n=l.a,p=n.L,q=l.b?l.b.a.L:null;if(p||q){b.uniform4f(d,n.g,n.h,n.m,n.b);if(q){n=m.f;l=m.a;for(var t=0;t<q.length;t++)MV(n,l,q[t])}if(p)for(n=m.f,m=m.a,l=0;l<p.length;l++)MV(n,m,p[l])}}}} +dW.prototype.b=function(a){var b=a.data,c=b.a;if(!c||null==c.i||!ny(Iy(c)))return 2;var d=a.a;if(d.L)return 2;var e=0,f=Iy(c).a;for(c=0;c<f.length;c++){var g=f[c],h=0;if(null!=g.a)for(var k=g.a,l=0;l<k.length;l++){var m=wx(k[l]);if(null!=m.b)var n=null==m.b?0:m.b;else{var p=ex(m);n=BI(p);Vc(p)}h=null!=m.c?h+3*(n-2):h+gx(m);h+=6*(n-jx(m))}null!=g.c&&(g=Jx(g),h+=3*(Bx(g)-2),h-=6*Dx(g));e+=2*h}e*=this.a.a;c=new hr(e);h=b.b.a[3];a=a.a.c;b=b.c;for(g=0;g<f.length;g++){k=h[g].ka();k=ZV(a,k);l=h[g].m;if(null!= +l.a)for(m=l.a,n=0;n<m.length;n++){var q=m[n],t=b;p=k;var v=c,u=wx(q);q=(null==q.b?0:q.b)/t;var w=ex(u),y=null!=u.b?null==u.b?0:u.b:BI(w),A=new Float32Array(2*y);DI(w,y,t,A);Vc(w);if(fx(u)){var z=hx(u);for(t=0;t<z.length;t+=3){w=z[t+0];var C=z[t+1],I=z[t+2];hW(this,A,w,C,I,q,p,v)}}else if(null!=u.c){z=null==u.c?-1:u.c;var S=y-2;for(t=0;t<S;t++)w=z,C=(z+t+1)%y,I=(z+t+2)%y,hW(this,A,w,I,C,q,p,v)}z=0;I=null!=u.h||null!=u.o?lx(u):null;S=0;u=null!=u.g||null!=u.C?kx(u):null;var ca=0;for(t=0;t<y;t++){var Z= +!0;w=t;C=t+1;u&&u[ca]==w&&(Z=!1,ca++);if(C==y||I&&I[S]==C){var ha=C;C=z;z=ha;S++}Z&&iW(this,A,C,w,q,p,v)}}if(null!=l.c){p=Jx(l);n=b;l=c;v=Ax(p);q=null!=p.g?null==p.g?0:p.g:CI(v);m=new Float32Array(3*q);EI(v,q,n,m);Vc(v);n=-Infinity;for(v=0;v<m.length;v+=3)q=m[v+2],q>n&&(n=q);v=Cx(p);q=2;p=null!=p.a||null!=p.i?Ex(p):null;y=0;t=v[0];w=v[1];for(C=!0;q<v.length;)A=t,t=w,w=v[q++],C?jW(this,m,A,w,t,n,k,l):jW(this,m,A,t,w,n,k,l),C=!C,p&&q==p[y]&&(t=v[q++],w=v[q++],y++,C=!0)}}g=c.g;h=c.c;f=c.b;a=c.a;k=a>> +1>>1;a/=this.a.a;for(b=0;b<k;b++)g[k+b]=g[b];for(b=a;b<2*a;b+=3)g=8*b,k=8*(b+2),l=h[g],m=h[g+1],n=h[g+2],h[g]=h[k],h[g+1]=h[k+1],h[g+2]=h[k+2],h[k]=l,h[k+1]=m,h[k+2]=n;for(b=a;b<2*a;b++)h=16*b,f[h+8]=254-f[h+8],f[h+9]=254-f[h+9],f[h+10]=254-f[h+10];c.a*=2;e=lr(this.i,e);nr(this.i,e,c.b);jO(d.a,e);d.L=e.a;return 2};function hW(a,b,c,d,e,f,g,h){var k=b[2*d+0];d=b[2*d+1];var l=b[2*e+0];e=b[2*e+1];kW(a,b[2*c+0],b[2*c+1],f,0,0,1,f,g,h);kW(a,k,d,f,0,0,1,f,g,h);kW(a,l,e,f,0,0,1,f,g,h)} +function jW(a,b,c,d,e,f,g,h){var k=b[3*c+0],l=b[3*c+1];c=b[3*c+2];var m=b[3*d+0],n=b[3*d+1];d=b[3*d+2];var p=b[3*e+0],q=b[3*e+1];b=b[3*e+2];e=-(q-l)*(d-c)+(b-c)*(n-l);var t=+(p-k)*(d-c)-(b-c)*(m-k),v=-(p-k)*(n-l)+(q-l)*(m-k),u=Math.sqrt(e*e+t*t+v*v);e=e/u*-1;t=t/u*-1;v=v/u*-1;kW(a,k,l,c,e,t,v,f,g,h);kW(a,m,n,d,e,t,v,f,g,h);kW(a,p,q,b,e,t,v,f,g,h)} +function iW(a,b,c,d,e,f,g){var h=b[2*c+0];c=b[2*c+1];var k=b[2*d+0];b=b[2*d+1];d=c-b;var l=k-h,m=Math.sqrt(d*d+l*l);d/=m;l/=m;kW(a,h,c,0,d,l,0,e,f,g);kW(a,k,b,0,d,l,0,e,f,g);kW(a,k,b,e,d,l,0,e,f,g);kW(a,k,b,e,d,l,0,e,f,g);kW(a,h,c,e,d,l,0,e,f,g);kW(a,h,c,0,d,l,0,e,f,g)}function kW(a,b,c,d,e,f,g,h,k,l){var m=l.c,n=l.b,p=l.f,q=l.a,t=q>>1;m[t]=16*b;m[t+1]=16*c;m[t+2]=16*d;m[t+3]=16*h;n[q+8]=127*(e+1);n[q+9]=127*(f+1);n[q+10]=127*(g+1);n[q+11]=0;p[t+6]=k.x;p[t+7]=k.y;l.a+=a.a.a};function lW(){this.s=this.g=this.C=this.f=this.h=this.c=this.ea=this.o=this.u=this.A=this.m=this.l=this.j=this.i=this.b=this.G=this.v=this.B=this.D=null;this.H={}}var mW="#define _b 8\n#define _c 8000\n#define _d "+QB+"\n#define _e 2\n#define _f 16\n#define _g 8\n#define _h 22\n\n"; +lW.prototype.a=function(a,b){b="#define _a "+b.f+"\n";var c=this.H[b];c||(c=zV(a,mW+b+"precision highp float;\n#if _a==1\nuniform float d;varying vec3 e;\n#endif\nuniform vec4 f;uniform vec3 g,h;uniform mat4 i;uniform float k,q,r;\n#if _a==1\nuniform mat4 l;vec3 H(vec3 t){const float u=6371010.;float v,w,x,A,B,C,D,E,F,G;v=t.x;w=exp(t.y);x=w*w;A=2.*w/(1.+x);B=(x-1.)/(1.+x);C=t.z*u*A;D=C+u;E=D*A*cos(v);F=D*A*sin(v);G=D*B;return vec3(E,F,G);}vec4 I(vec3 t){vec4 u,x;u=i*vec4(t,1);vec3 v,w;v=t;v/=k;v+=g+h;v.xy-=.5;v.y=-v.y;v*=3.141592653589793*2.;w=H(v);x=l*vec4(w,1);x/=x.w;u/=u.w;return mix(u,x,d);}vec3 J(vec3 t){t/=k;t+=g+h;t.xy-=.5;t.y=-t.y;t*=3.141592653589793*2.;vec3 u=mat3(l)*H(t);return normalize(u);}\n#else\nvec4 I(vec3 t){return i*vec4(t,1);}\n#endif\nvec3 K(vec3 t,vec3 u){vec3 v=t-g+(u-h);return v*k;}vec3 L(vec3 t){vec3 u,v;u=vec3(f.x,f.y,0);v=t*f.w;v.xy*=1./float(_f);return K(u,v);}vec4 M(vec3 t){vec3 u=L(t);return I(u);}float N(vec4 t){float u,v;u=1./float(_h+1);v=1.-u-f.z*u;return t.z*u+t.w*v;}void O(vec3 f){\n#if _a==1\nvec3 t=L(f);e=J(t);\n#endif\n}varying vec2 n;attribute vec2 o;uniform vec2 p;void main(){vec3 f=vec3(o.x,o.y,0);O(f);gl_Position=M(f);gl_Position.xy+=p*gl_Position.w;gl_Position.z=gl_Position.w*q;gl_Position.z=N(gl_Position);n=f.xy/(256.*float(_f));n*=r;}",mW+ +b+"precision highp float;\n#if _a==1\nuniform float d;varying vec3 e;\n#endif\nfloat w(){\n#if _a==1\nfloat u,v;u=dot(e,vec3(-1.,1,-1.));v=clamp((u-.5)/4.+1.,.5,1.);return mix(1.,v,d);\n#else\nreturn 1.;\n#endif\n}precision highp float;varying vec2 n;uniform float s;uniform sampler2D t;void main(){vec4 u=texture2D(t,n);if(u.a==0.)discard;float v=w();gl_FragColor=vec4(u.rgb*v,u.a*s);}",["o"]),this.H[b]=c);this.g=c}; +lW.prototype.bind=function(a,b){this.a(a,b);if(this.s!=this.g){var c=this.g,d=function(b){return a.getUniformLocation(c,b)};this.D=d("a");this.B=d("b");this.v=d("c");this.G=d("d");this.b=d("f");this.i=d("g");this.j=d("h");this.l=d("i");this.m=d("j");this.A=d("k");this.u=d("l");this.o=d("m");this.ea=d("p");this.c=d("q");this.h=d("r");this.f=d("s");this.C=d("t");this.s=this.g}a.useProgram(this.s);this.D&&a.uniform4fv(this.D,b.s.value);this.B&&a.uniform4fv(this.B,b.o.value);this.v&&a.uniform1f(this.v, +b.b.value);this.G&&a.uniform1f(this.G,b.c.value);this.b&&a.uniform4fv(this.b,b.C.value);this.i&&a.uniform3fv(this.i,b.g.value);this.j&&a.uniform3fv(this.j,b.h.value);this.l&&a.uniformMatrix4fv(this.l,!1,b.i.value);this.m&&a.uniform1f(this.m,b.j.value);this.A&&a.uniform1f(this.A,b.m.value);this.u&&a.uniformMatrix4fv(this.u,!1,b.a.value);this.o&&a.uniform1i(this.o,b.l.value);this.ea&&a.uniform2fv(this.ea,b.ea.value);this.c&&a.uniform1f(this.c,b.I.value);this.h&&a.uniform1f(this.h,b.M.value);this.f&& +a.uniform1f(this.f,b.L.value);this.C&&a.uniform1i(this.C,b.K.value)};function nW(a,b){this.a=a;this.o=b;this.c=yV(a,lW);this.f=new EV(1,[[2,5126]]);this.m=this.g=this.l=0;this.i=this.h=null;this.j=0;this.b=new tO}function oW(a,b,c,d,e,f){for(var g=new Uint32Array(b*b),h=0,k=0;k<b;k++)for(var l=0;l<b;l++)0==l||0==k||l==b-1||k==b-1?g[h++]=e:l%c&&k%c?g[h++]=d:g[h++]=f;c=a.a.createTexture();Jo(c,3);No(c,9729);Oo(c,9729);Mo(c,10497);g=new Uint8Array(g.buffer);Uo(c,g,b,b,6408,5121,0);a.h=c} +function pW(a,b,c,d){function e(a){var b=0|Math.round(255*a[0]);b|=Math.round(255*a[1])<<8;b|=Math.round(255*a[2])<<16;return b|=Math.round(255*a[3])<<24}if(2==c){c=dI;var f=eI;var g=fI}else c=aI,f=bI,g=cI;b=Yn(Math.round(b),1,2);oW(a,128*b,16*b,e(c),e(f),e(g));d=JV(a.a,0,4096,d,0,4096,d);a.i=d.buffer;a.j=d.size} +function qW(a,b,c,d,e,f,g){for(var h=0;h<c.length;++h)for(var k=c[h].a,l=0;l<k.length;++l){var m=a,n=b,p=k[l],q=d,t=e,v=f,u=g,w=m.a;RV(w,q);for(var y=[],A=[],z=p.a,C=0;C<z.length;++C){var I=z[C];qO(I)?A.push(I):I.data&&t?I.N.getZoom()==p.b.zoom&&A.push(sO(I.N,-1)):I.data&&4!=I.N.Ea()&&y.push(I)}xO(m.b,y,A,p.b,t,u);p=m.b.a.zoom;n.uniform1f(m.c.h,.5<v-p?4:2);t=m.b.a.a;if(t.length)for(u=m.a,y=1/Math.pow(2,p),A=0;A<t.length;A++)v=t[A],0>=v.a||(z=v.x*y,C=v.y*y,n.uniform1f(m.c.f,v.a),n.uniform4f(m.c.b, +z,C,p,y/256),u.drawArrays(4,0,m.j));RV(w,q)}};function rW(){this.u=this.b=this.l=this.s=this.m=this.B=this.o=this.v=this.C=this.h=this.g=this.f=this.c=this.K=this.H=this.i=this.j=this.I=this.J=this.A=this.D=this.G=null;this.L={}}var sW="#define _b 8\n#define _c 8000\n#define _d "+QB+"\n#define _e 2\n#define _f 16\n#define _g 8\n#define _h vec4(0., 0., 0., 0.2)\n#define _i 2\n#define _j 9\n#define _k 6\n#define _l 3\n#define _m 0\n#define _n 1\n#define _o 2\n#define _p 4\n#define _q 5\n#define _r 12\n#define _s 0\n#define _t 8\n#define _u 2\n#define _v 1\n#define _w 22\n\n"; +rW.prototype.a=function(a,b){b="#define _a "+b.f+"\n";var c=this.L[b];c||(c=zV(a,sW+b+"precision highp float;uniform vec4 a,b,f,B;uniform float c,n,o,A,C;vec2 Q(vec2 E){return (E*b.xy+b.xy)*.5;}vec2 R(vec2 E){return (E*b.zw-vec2(.5))*2.;}vec2 S(vec4 E){return vec2(E.g+E.b*256.,E.a);}uniform sampler2D g;float T(float E){return mod(E,32.)/31.;}void U(vec2 E,out float F,out vec2 G){vec4 H=texture2D(g,(floor(E*65535.+.5)+.5)*f.zw);H=floor(H*255.+.5);F=T(H.r);G=S(H);}\n#if _a==1\nuniform float h;varying vec3 i;\n#endif\nuniform vec3 k,l;uniform mat4 m;\n#if _a==1\nuniform mat4 p;vec3 V(vec3 E){const float F=6371010.;float G,H,I,J,K,L,M,N,O,P;G=E.x;H=exp(E.y);I=H*H;J=2.*H/(1.+I);K=(I-1.)/(1.+I);L=E.z*F*J;M=L+F;N=M*J*cos(G);O=M*J*sin(G);P=M*K;return vec3(N,O,P);}vec4 W(vec3 E){vec4 F,I;F=m*vec4(E,1);vec3 G,H;G=E;G/=o;G+=k+l;G.xy-=.5;G.y=-G.y;G*=3.141592653589793*2.;H=V(G);I=p*vec4(H,1);I/=I.w;F/=F.w;return mix(F,I,h);}\n#else\nvec4 W(vec3 E){return m*vec4(E,1);}\n#endif\nvec3 X(vec3 E,vec3 F){vec3 G=E-k+(F-l);return G*o;}vec3 Y(vec2 E,vec2 F,vec2 G){vec3 H,I;H=vec3(E.x,F.x,G.x)*65535.+.5;\n#if _a==1\nH-=fract(H);\n#else\nH=floor(H);\n#endif\nH=H/65536.;H=(fract(H+.5)-.5)*4.;I=vec3(E.y,F.y,G.y)*65535.;I/=1073741824.;return X(H,I);}vec4 Z(vec2 E,vec2 F,vec2 G){vec3 H=Y(E,F,G);return W(H);}varying vec2 r;varying float s,t;attribute vec4 u;attribute vec4 v;attribute vec2 w;attribute vec4 x;void main(){vec2 E,I,J;E=floor(x.xy*32767.+.5)*(1./float(_f));bool F,G;F=w.y>=.5;G=fract(2.*w.y)>0.;if(G)E.y*=sin(n);r=floor(x.zw*32767.+.5)*B.zw;vec4 H=Z(u.yx,u.wz,v.yx);I=Q(H.xy/H.w);I+=vec2(E.x,-E.y)*c;I=mix(I,floor(I+.5),A);gl_Position.xy=R(I);gl_Position.z=w.x;gl_Position.w=1.;if(!G&&F)gl_Position.y+=sin(n)*C/a.y;t=float(G);U(v.zw,s,J);float K=(J.x+J.y)*s*H.w;if(K<=0.)gl_Position=vec4(0);}", +sW+b+"precision highp float;precision highp float;\n#if _a==1\nvarying vec3 i;\n#endif\nprecision highp float;varying vec2 r;varying float s,t;uniform sampler2D D;const vec4 E=vec4(1);void main(){vec4 F=texture2D(D,r);if(t!=0.)F=E;F*=s;if(F.a==0.)discard;gl_FragColor=F;}",["u","v","w","x"]),this.L[b]=c);this.b=c}; +rW.prototype.bind=function(a,b){this.a(a,b);if(this.u!=this.b){var c=this.b,d=function(b){return a.getUniformLocation(c,b)};this.G=d("a");this.D=d("b");this.A=d("c");this.J=d("d");this.I=d("e");this.j=d("f");this.i=d("g");this.H=d("h");this.K=d("j");this.c=d("k");this.f=d("l");this.g=d("m");this.h=d("n");this.C=d("o");this.v=d("p");this.o=d("q");this.B=d("A");this.m=d("B");this.s=d("C");this.l=d("D");this.u=this.b}a.useProgram(this.u);this.G&&a.uniform4fv(this.G,b.s.value);this.D&&a.uniform4fv(this.D, +b.o.value);this.A&&a.uniform1f(this.A,b.b.value);this.J&&a.uniform4fv(this.J,b.B.value);this.I&&a.uniform1i(this.I,b.A.value);this.j&&a.uniform4fv(this.j,b.v.value);this.i&&a.uniform1i(this.i,b.u.value);this.H&&a.uniform1f(this.H,b.c.value);this.K&&a.uniform4fv(this.K,b.C.value);this.c&&a.uniform3fv(this.c,b.g.value);this.f&&a.uniform3fv(this.f,b.h.value);this.g&&a.uniformMatrix4fv(this.g,!1,b.i.value);this.h&&a.uniform1f(this.h,b.j.value);this.C&&a.uniform1f(this.C,b.m.value);this.v&&a.uniformMatrix4fv(this.v, +!1,b.a.value);this.o&&a.uniform1i(this.o,b.l.value);this.B&&a.uniform1f(this.B,b.H.value);this.m&&a.uniform4fv(this.m,b.G.value);this.s&&a.uniform1f(this.s,b.J.value);this.l&&a.uniform1i(this.l,b.D.value)};function tW(a,b){var c=1-a.label.g/65534;b&&(c-=.5);(0==a.type||1==a.type)&&1>c&&(c+=1/65536);return c};function uW(a,b,c,d){this.g=a;this.i=b;this.h=yV(a,rW);this.f=d;b=6;d&&(b+=6);this.a=new EV(b,[[4,5123],[4,5123],[2,5126],[4,5122]]);this.j=new ir(a,this.a.a,this.a.b,65536);this.c=c} +function vW(a,b,c,d){for(var e=a.g,f=a.i,g=a.a,h=!1,k=0;k<b.length;++k){var l=b[k];if(l.b&&l.b.a.P[d]){h=!0;break}if(l.a.P[d]){h=!0;break}}if(h){TV(e,c,4,3,1,2,1);fr(a.c,5);f.D.set(5);k=a.c.c;l=a.c.a;f.G.set(k,l,1/k,1/l);f.H.set(c.C);f.J.set(143);c=hq(e);a.h.bind(c,f);FV(e,g);for(k=0;k<b.length;++k)l=b[k],l.b?(f=l.b.a.P[d],c=l.a.P[d]):(f=l.a.P[d],c=null),(f||c)&&NV(e,g,f,c);iq(e);GV(e,g);gr(a.c)}} +uW.prototype.b=function(a,b){a=a.a;var c=a.a,d=a.u,e=a.f,f=a.c,g=this.a.f,h=b.a;if(!h.length)return 2;for(var k=new Uint32Array(h.length*this.a.h),l=new Float32Array(k.buffer),m=0,n=0;n<h.length;++n){var p=h[n],q=p,t=q.label.i&&this.f,v=p.label.b,u=pI(v.a,a.b,a.g),w=pI(v.b,a.b,a.h);v=pI(v.altitude,a.b,0);var y=0,A=0,z=0,C=0,I=0,S=0,ca=0,Z=0,ha=wW(d,e.a[p.a],q.text,c);ha&&(A=q.oa,C=q.b,y=A,A+=q.width,z=C-q.height/2,C+=q.height/2,y*=16,A*=16,z*=16,C*=16,S=ha.left+q.g.left,Z=ha.top+q.g.top,I=S,S+=q.g.width, +ca=Z,Z+=q.g.height);p=ZV(f,p.a);q=tW(q,this.f);p=oI(p.x,p.y);ha=this.f?1:0;for(var ea,ja,Y,ma,Ga,wa,Kd=0;Kd<=ha;Kd++)wa=t?.5:0,Kd?(ea=-8,ja=8,Y=t?-1144:0,ma=0,wa+=.25,Ga=.5):(ea=y,ja=A,Y=z,ma=C,Ga=q),k[m+0]=u,k[m+1]=w,k[m+2]=v,k[m+3]=p,l[m+4]=Ga,l[m+5]=wa,k[m+6]=oI(ea,ma),k[m+7]=oI(I,Z),m+=g,k[m+0]=u,k[m+1]=w,k[m+2]=v,k[m+3]=p,l[m+4]=Ga,l[m+5]=wa,k[m+6]=oI(ea,Y),k[m+7]=oI(I,ca),m+=g,k[m+0]=u,k[m+1]=w,k[m+2]=v,k[m+3]=p,l[m+4]=Ga,l[m+5]=wa,k[m+6]=oI(ja,Y),k[m+7]=oI(S,ca),m+=g,k[m+0]=u,k[m+1]=w,k[m+ +2]=v,k[m+3]=p,l[m+4]=Ga,l[m+5]=wa,k[m+6]=oI(ea,ma),k[m+7]=oI(I,Z),m+=g,k[m+0]=u,k[m+1]=w,k[m+2]=v,k[m+3]=p,l[m+4]=Ga,l[m+5]=wa,k[m+6]=oI(ja,Y),k[m+7]=oI(S,ca),m+=g,k[m+0]=u,k[m+1]=w,k[m+2]=v,k[m+3]=p,l[m+4]=Ga,l[m+5]=wa,k[m+6]=oI(ja,ma),k[m+7]=oI(S,Z),m+=g}m&&(c=PV(this.j,k),jO(a.a,c),a.P[b.b]=c.a[0]);return 2};function xW(a,b){this.f=a;this.j=b;this.i=yV(a,lW);this.c=new EV(1,[[2,5126]]);this.h=0;this.g=null;this.a=0}function yW(a,b){a=a.b||a;return 2!=a.N.Ea()&&b.u?null:a.a.C}function zW(a){return a.b?a.a.C:null} +xW.prototype.b=function(a){var b,c=this.f;if(!a.a.C)return 2;var d=a.a.a,e=a.data.b.a[5];for(b=0;b<a.a.C.length;b++){var f=a.a.C[b],g=f.b,h=4;g.Db()&&1!=g.Yb().format&&(h=1);var k=f;h=iO(d,g.Yd()*g.Xd()*h);k.Xb=d.c[h];Jo(f.Xb,3);Mo(f.Xb,33071);k=f.Xb;No(k,9729);Oo(k,9729);XQ(c,g);f.a=1-e[b].za/65535}return 2};function AW(){this.s=this.b=this.m=this.l=this.v=this.o=this.u=this.B=this.h=this.g=this.f=this.c=this.J=this.G=this.i=this.j=this.H=this.I=this.A=this.C=this.D=null;this.K={}}var BW="#define _b 8\n#define _c 8000\n#define _d "+QB+"\n#define _e 2\n#define _f 16\n#define _g 8\n#define _h vec4(0., 0., 0., 0.2)\n#define _i 2\n#define _j 9\n#define _k 6\n#define _l 3\n#define _m 0\n#define _n 1\n#define _o 2\n#define _p 4\n#define _q 5\n#define _r 12\n#define _s 0\n#define _t 8\n#define _u 2\n#define _v 1\n#define _w 22\n\n"; +AW.prototype.a=function(a,b){b="#define _a "+b.f+"\n";var c=this.K[b];c||(c=zV(a,BW+b+"precision highp float;uniform vec4 a,f;uniform float c,o,r;vec2 pa(vec4 F){return vec2(F.g+F.b*256.,F.a);}uniform sampler2D g;float qa(float F){return mod(F,32.)/31.;}void ra(vec2 F,out float G,out vec2 H,out bool I){vec4 J=texture2D(g,(floor(F*65535.+.5)+.5)*f.zw);J=floor(J*255.+.5);G=qa(J.r);I=mod(J.r/32.,2.)>=1.;H=pa(J);}\n#if _a==1\nuniform float h;varying vec3 i;\n#endif\nuniform vec3 k,l;uniform mat4 m;\n#if _a==1\nuniform mat4 p;vec3 sa(vec3 F){const float G=6371010.;float H,I,J,K,L,M,N,O,P,Q;H=F.x;I=exp(F.y);J=I*I;K=2.*I/(1.+J);L=(J-1.)/(1.+J);M=F.z*G*K;N=M+G;O=N*K*cos(H);P=N*K*sin(H);Q=N*L;return vec3(O,P,Q);}vec4 ta(vec3 F){vec4 G,J;G=m*vec4(F,1);vec3 H,I;H=F;H/=o;H+=k+l;H.xy-=.5;H.y=-H.y;H*=3.141592653589793*2.;I=sa(H);J=p*vec4(I,1);J/=J.w;G/=G.w;return mix(G,J,h);}\n#else\nvec4 ta(vec3 F){return m*vec4(F,1);}\n#endif\nvec3 ua(vec3 F,vec3 G){vec3 H=F-k+(G-l);return H*o;}vec3 va(vec2 F,vec2 G,vec2 H){vec3 I,J;I=vec3(F.x,G.x,H.x)*65535.+.5;\n#if _a==1\nI-=fract(I);\n#else\nI=floor(I);\n#endif\nI=I/65536.;I=(fract(I+.5)-.5)*4.;J=vec3(F.y,G.y,H.y)*65535.;J/=1073741824.;return ua(I,J);}varying vec3 s;varying vec4 t;attribute vec2 u;attribute vec4 v;attribute vec4 w;attribute vec4 x;attribute vec4 A;attribute vec4 B;attribute vec2 C;attribute vec4 D;void main(){vec2 F,G,I,Y,ba,ja,ka,la,oa;F=a.xy*.5;G=2.*a.zw;float H,L,M,N,O,P,Q,R,S,T,ca,ea,fa,ga,ha,ma,na;bool J,K;ra(x.zw,H,I,J);K=D.x>0.;L=floor(A.w*32767.+.5)/float(_f);M=floor(C.x*32767.+.5)/float(_f);N=floor(C.y*32767.+.5);N=N>0.?N:65536.+N;O=floor(N/256.);P=O*.5;Q=mod(N,256.)*.5;R=floor(D.y*255.+.5);S=1.;if(R<=1.)S=-1.;T=1.;if(R==1.)T=-1.;if(R==2.)T=-1.;vec3 U,V,W,Z,da;U=va(v.yx,v.wz,x.yx);V=va(w.yx,w.wz,x.yx);W=S==-1.?U:V;vec4 X,aa,ia;X=ta(W);Y=F*X.xy/X.w;Z=S==-1.?V:U;aa=ta(Z);ba=F*aa.xy/aa.w;ca=length(ba.xy-Y.xy);da=floor(A.xyz*32767.+.5)/float(_c);M+=P;M=J&&K?M*-1.:M;ea=u.x*ca-M;ea+=L*da.z;fa=ca+L*(da.x+da.y);ga=-ea/fa;ha=step(ga,0.)+step(1.,ga);ia=vec4(Y,ba);ja=normalize(ba-Y);ka=vec2(-ja.y,ja.x);la=S==1.?da.yx:da.xy;ia+=ka.xyxy*L*S;ia+=vec4(-la.xx,la.yy)*ja.xyxy*L;ga=S<0.?ga:1.-ga;Y=mix(ia.xy,ia.zw,ga);ma=1./c-r/c;Y-=(P+ma)*ja;Y+=(Q+ma)*ka*T*S;na=u.y;gl_Position=vec4(Y*G,na,1);gl_Position.xy*=1.-ha;t.zw=vec2(P,Q)*2.*c;t.xy=vec2(S,T)*(.5-float(J))*(t.zw+2.*ma)/t.zw;gl_Position.xy*=sign(H);gl_Position.xy*=sign(I.x+I.y);oa=mix(floor(B.xy*32767.+.5),floor(B.zw*32767.+.5),t.xy+.5)/float(_e);s=vec3(oa,H);}", +BW+b+"precision highp float;precision highp float;\n#if _a==1\nvarying vec3 i;\n#endif\nprecision highp float;uniform float r;varying vec3 s;varying vec4 t;uniform sampler2D E;uniform vec4 F;void main(){vec2 G,I;G=s.xy*F.zw;vec4 H=texture2D(E,G);I=.5-(abs(t.xy)-.5)*t.zw;float J=clamp(min(I.x,I.y),0.,1.);J=min(r+J,1.);H*=s.z*J;if(step(H.a,0.)>.5)discard;gl_FragColor=H;}","uvwxABCD".split("")),this.K[b]=c);this.b=c}; +AW.prototype.bind=function(a,b){this.a(a,b);if(this.s!=this.b){var c=this.b,d=function(b){return a.getUniformLocation(c,b)};this.D=d("a");this.C=d("b");this.A=d("c");this.I=d("d");this.H=d("e");this.j=d("f");this.i=d("g");this.G=d("h");this.J=d("j");this.c=d("k");this.f=d("l");this.g=d("m");this.h=d("n");this.B=d("o");this.u=d("p");this.o=d("q");this.v=d("r");this.l=d("E");this.m=d("F");this.s=this.b}a.useProgram(this.s);this.D&&a.uniform4fv(this.D,b.s.value);this.C&&a.uniform4fv(this.C,b.o.value); +this.A&&a.uniform1f(this.A,b.b.value);this.I&&a.uniform4fv(this.I,b.B.value);this.H&&a.uniform1i(this.H,b.A.value);this.j&&a.uniform4fv(this.j,b.v.value);this.i&&a.uniform1i(this.i,b.u.value);this.G&&a.uniform1f(this.G,b.c.value);this.J&&a.uniform4fv(this.J,b.C.value);this.c&&a.uniform3fv(this.c,b.g.value);this.f&&a.uniform3fv(this.f,b.h.value);this.g&&a.uniformMatrix4fv(this.g,!1,b.i.value);this.h&&a.uniform1f(this.h,b.j.value);this.B&&a.uniform1f(this.B,b.m.value);this.u&&a.uniformMatrix4fv(this.u, +!1,b.a.value);this.o&&a.uniform1i(this.o,b.l.value);this.v&&a.uniform1f(this.v,b.Bb.value);this.l&&a.uniform1i(this.l,b.D.value);this.m&&a.uniform4fv(this.m,b.G.value)};function CW(a,b,c){this.f=a;this.h=b;this.g=yV(a,AW);this.a=new EV(6,[[2,5126],[4,5123],[4,5123],[4,5123],[4,5122],[4,5122],[2,5122],[4,5121]]);this.i=new ir(a,this.a.a,this.a.b,65536);this.c=c} +function DW(a,b,c,d){for(var e=a.f,f=a.h,g=a.a,h=a.g,k=!1,l=0;l<b.length;++l){var m=b[l];if(m.b&&m.b.a.S[d]){k=!0;break}if(m.a.S[d]){k=!0;break}}if(k){TV(e,c,4,3,1,2,1);fr(a.c,5);f.D.set(5);l=a.c.c;c=a.c.a;f.G.set(l,c,1/l,1/c);FV(e,g);l=hq(e);h.bind(l,f);for(l=0;l<b.length;++l)b[l].b?(f=b[l].b.a.S[d],h=b[l].a.S[d]):(f=b[l].a.S[d],h=null),(f||h)&&NV(e,g,f,h);iq(e);GV(e,g);gr(a.c)}} +CW.prototype.b=function(a,b){a=a.a;var c=a.c,d=a.a,e=a.u,f=a.f,g=this.a.f,h=b.a;if(!h.length)return 2;e&&0==e.a&&e.Na(d);for(var k=0,l=0;l<h.length;++l){var m=h[l],n=m.label.a.a-1;k+=n*this.a.h}var p=[0,1,2,0,2,3];k=new Uint32Array(k);var q=new Float32Array(k.buffer),t=0;for(l=0;l<h.length;++l){m=h[l];var v=ZV(c,m.a),u=0,w=0,y=0,A=0;n=wW(e,f.a[m.a],"",d);var z=m.g;n&&(u=n.left+z.left,w=n.top+z.top,y=u+z.width,A=w+z.height);u*=2;w*=2;y*=2;A*=2;z=m.label.a;n=z.a-1;var C=m.j.width,I=m.j.height,S=tW(m), +ca=0,Z=0,ha=SK(z.b,z.f),ea=0!=m.f?eL(z,n):0,ja=0;0<=ea&&(1==z.h?ja=ea/2:3==z.h&&(ja=ea));var Y=pI(z.altitude,a.b,0);v=oI(v.x,v.y);u=oI(u,w);y=oI(y,A);A=oI(16*m.b,C<<8|I);w=1==z.h;for(var ma=I=C=0;ma<n;++ma){var Ga=pI(gL(z,ma),a.b,a.g),wa=pI(hL(z,ma),a.b,a.h),Kd=pI(gL(z,ma+1),a.b,a.g),xy=pI(hL(z,ma+1),a.b,a.h);0!=m.f&&(ca=z.i[Math.floor(ma)],Z=z.i[Math.ceil(ma+1)],0>ea&&(0==ma&&(ca=-ea/2),ma==n-1&&(Z=-ea/2)));for(var qj=SK(z.b,ma+1)-SK(z.b,ma),rj=qj?(C-ha)/qj:0,yy=oI(8E3*Yn(ca,-4,4),8E3*Yn(Z,-4,4)), +jZ=oI(8E3*Yn(I-ja,-4,4),16*m.f),zy=0;zy<p.length;zy++){var kZ=((w?1:0)&255|(p[zy]&255)<<8|0)>>>0;q[t+0]=rj;q[t+1]=S;k[t+2]=Ga;k[t+3]=wa;k[t+4]=Kd;k[t+5]=xy;k[t+6]=Y;k[t+7]=v;k[t+8]=yy;k[t+9]=jZ;k[t+10]=u;k[t+11]=y;k[t+12]=A;k[t+13]=kZ;t+=g}C+=qj;I+=ca+Z}}t&&(c=PV(this.i,k),jO(a.a,c),a.S[b.b]=c.a[0]);return 2};function EW(a){this.g=a;this.ga=this.fa=0;this.va=1;this.C=16;this.f=this.g?new EV(1,[[4,5123],[4,5123],[4,5123],[4,5121],[2,5126],[1,5126,!0]]):new EV(1,[[4,5122],[4,5123],[4,5121],[1,5126,!0]]);this.b=new Uint32Array(1024*this.f.f);this.H=new Float32Array(this.b.buffer);this.u=this.M=this.l=this.G=this.S=this.P=this.j=this.i=this.s=this.D=this.V=this.a=0;this.v=[];this.c=this.m=this.B=this.A=!1;this.h=this.U=0;this.T=!0;this.o=this.Z=this.I=this.O=this.K=this.J=this.Y=this.W=this.L=this.ha=this.ja= +this.ia=this.ra=this.pa=0}EW.prototype.reset=function(a,b,c,d){this.fa=a;this.ga=b;this.va=c;this.C=d;this.l=this.G=this.S=this.P=this.j=this.i=this.s=this.D=this.a=0;this.c=this.m=this.B=this.A=!1;this.o=this.Z=this.I=this.O=this.K=this.J=this.Y=this.W=this.L=this.ha=0}; +function FW(a,b,c){a.s=0;a.i=0;a.j=0;switch(b){case 0:a.s=0;break;case 1:case 2:case 4:a.s=10;break;case 3:a.s=8;break;default:a.s=0}switch(c){case 0:a.i=0;break;case 1:case 2:case 4:a.i=20;break;case 3:a.i=16;break;default:a.i=0}2==b&&(a.j|=32);2==c&&(a.j|=64)}function GW(a,b){a.O=oI(b.x,b.y)}function HI(a){a.c=!1;GI(a,0,0);a.g&&HW(a);a.c=!1}function JI(a){a.V=a.a;a.h=0;a.g&&(a.v=[]);a.A=!1;a.B=!1;a.m=!1;a.c=!1;a.M=0;a.u=0;a.T=!1} +function KI(a){if(3>a.h)HI(a);else if(a.c)if(GI(a,a.pa,a.ra),a.T){GI(a,a.ia,a.ja);var b=a.g?6:4,c=a.V+b;b=a.a-a.f.f+b;a.b[c]&=-1342242561;a.b[c]|=256-(a.b[b]>>16&255)<<8;a.c=!1}else HI(a);else HI(a)} +function GI(a,b,c){0==a.h&&(a.pa=b,a.ra=c);1==a.h&&(a.ia=b,a.ja=c);a.h++;var d=a.P;a.P=b;var e=a.S;a.S=c;var f=a.M;a.M=a.u;var g=a.U;1<a.h&&(a.U=Math.sqrt((b-d)*(b-d)+(c-e)*(c-e))/a.C,a.u+=a.U);a.A=a.B;a.B=a.m;a.m=a.c;var h=a.va/a.C;a.g?(a.W=a.J,a.Y=a.K,a.J=pI(d,h,a.fa),a.K=pI(e,h,a.ga),a.Z=g?f/g:0):(a.ha=a.L,a.L=qI(d,h,a.fa)|qI(e,h,a.ga)<<16);f=a.G;a.G=Math.round(Math.atan2(c-e,b-d)/Math.PI*128)&255;b=256-a.l&255;a.l=a.G-f&255;d=20/360*256;c=!1;a.c&&a.l>128-d&&a.l<128+d&&(a.l=0,c=!0);a.B?(d=a.D| +(a.A?0:a.s)|(a.m?0:a.i)|a.j,c&&(d|=a.i,d&=-65),a.I=f|(a.A?b:0)<<8|(a.m?a.l:0)<<16|d<<24,3==a.h&&(a.T=!0),a.g&&a.v.push(g),IW(a)):a.g&&HW(a);a.c=!0}function HW(a){for(var b=a.v.length,c=0,d=a.f.f,e=a.a-d+8,f=0;f<b;f++){var g=a.v[b-1-f];a.H[e-f*d]=c/g;c+=g}a.v=[]} +function IW(a){var b=a.f.f;if(a.a==a.b.length){if(a.a>=65536*b)return;var c=new Uint32Array(2*a.a);c.set(a.b);a.b=c;a.H=new Float32Array(a.b.buffer)}c=a.b;var d=a.a;a.g?(c[d+0]=a.W,c[d+1]=a.Y,c[d+2]=a.J,c[d+3]=a.K,c[d+4]=a.O,c[d+5]=a.o,c[d+6]=a.I,a.H[d+7]=a.Z,a.H[d+8]=0):(c[d+0]=a.ha,c[d+1]=a.L,c[d+2]=a.O,c[d+3]=a.o,c[d+4]=a.I);a.a+=b};function JW(a){this.c=a;this.b=[];this.i=[];this.a=0;this.j=-1}function KW(a,b){return cr(a.c,a.b[b])}function LW(a,b){return dr(a.c,a.b[b])}function MW(a,b){return-1!=a.b[b]?ar(a.c,a.b[b]):0}function NW(a,b){return-1!=a.b[b]?br(a.c,a.b[b]):0} +function OW(a,b,c,d,e,f,g){var h=a.c,k=a.b[b];a=a.i[b];-1!=k&&((b=0<h.g)||Wq(h),g instanceof Uint8Array?a?a&&$q(h,k,a,"array",c,d,e,f,g):$q(h,k,null,null,c,d,e,f,g):a?a&&$q(h,k,a,g.src,c,d,g.width,g.height,g):$q(h,k,null,null,c,d,g.width,g.height,g),b||Yq(h))}r=JW.prototype;r.Pb=function(){return 0==this.a?!1:this.j!=this.c.A?!0:1==this.a};r.ac=function(){}; +r.Na=function(a){for(var b=this.Ob(),c=0,d=0;d<b;d++){var e=this.zb(d),f=this.yb(d);var g=this.ac(d);if(e>this.c.c)this.b.push(-1),this.i.push(g),g=-1;else{if(g){var h=this.c;var k=g;if(k){var l=h.j[k];l?(l.a++,h=l.block):(e=Zq(h,e,f),-1!=e&&(h.j[k]=new Nq(e)),h=e)}else h=-1}else h=Zq(this.c,e,f);this.b.push(h);this.i.push(g);g=-1!=h?this.b.length-1:-1}-1!=g&&(c+=MW(this,g)*NW(this,g))}b=4;switch(this.c.m){case 6406:case 6409:b=1;break;case 6410:b=2;break;case 6407:b=3;break;case 6408:b=4}c*=b;b= +kO(a,this,sa);a.a-=a.g[b];a.g[b]=c;a.a+=a.g[b];this.a=1;return!0};r.Sb=function(){for(var a=0;a<this.b.length;a++){var b=this.b[a],c=this.i[a];if(-1!=b)if(c){var d=this.c;if(c&&!(0>b)){var e=d.j[c];e&&e.block==b&&(e.a--,0<e.a||(delete d.j[c],er(d,b)))}}else er(this.c,b)}this.b=[];this.i=[];this.a=0};r.Fa=function(a){0!=this.a||this.Na(a);if(this.Pb()){a=this.Ob();for(var b=0;b<a;b++)if(-1!=this.b[b]){var c=this.$b(b);c&&OW(this,b,0,0,this.zb(b),this.yb(b),c)}this.j=this.c.A;this.a=2}};function PW(a,b,c,d,e,f,g){this.b=a;this.a=b;this.zoom=c;this.type=d;this.width=e;this.height=f;this.name=g}function QW(a,b,c){JW.call(this,a);this.g=b;this.f=[];this.h={};this.l=-1;for(b=0;b<c.length;++b){var d=c[b],e=d.height;"stamp"==d.type&&(e=d.width);a&&e>a.v||this.f.push(d)}}F(QW,JW);r=QW.prototype;r.Ob=function(){return this.f.length};r.ac=function(a){return this.f[a].name}; +r.$b=function(a){a=this.f[a];var b=RA(this.g.a,a.b);if(!b)return null;switch(a.type){case "stamp":b=vA(b.v,a.a,a.zoom);break;case "startcap":b=vA(b.A,a.a,a.zoom);break;case "endcap":b=vA(b.u,a.a,a.zoom);break;default:throw"unknown icon type: "+a.type;}if(!b)return null;b=Zs(b,a.width,a.height,1);if("stamp"==a.type){var c=go("CANVAS");c.height=a.width;c.width=a.height+2;var d=c.getContext("2d");d.setTransform(0,1,1,0,0,0);d.drawImage(b,0,1);d.drawImage(b,0,1-a.height);d.drawImage(b,0,a.height+1);return c}return b}; +r.zb=function(a){a=this.f[a];var b=a.width;"stamp"==a.type&&(b=a.height+2);return b+1};r.yb=function(a){a=this.f[a];var b=a.height;"stamp"==a.type&&(b=a.width);a=4*Math.ceil((b+1)/4);8>a&&(a=8);return a};r.Na=function(a){if(a=QW.R.Na.call(this,a))for(var b=0;b<this.f.length;++b){var c=this.f[b],d=c.b+","+c.a+","+c.zoom+","+c.type;if(-1!=this.b[b]){var e=KW(this,b),f=LW(this,b);this.h[d]="stamp"==c.type?new pq(e+1,f,c.height,c.width):new pq(e,f,c.width,c.height)}}return a}; +r.Pb=function(){return this.l!=this.g.c||QW.R.Pb.call(this)};r.Fa=function(a){QW.R.Fa.call(this,a);this.l=this.g.c};function RW(a,b,c,d,e,f){b=b+","+c+","+d+","+e;0!=a.a||a.Na(f);return a.h[b]};function SW(){this.C=this.g=this.h=this.Hb=this.b=this.f=this.c=this.A=this.v=this.B=this.D=this.H=this.o=this.m=this.l=this.j=this.i=this.K=this.s=this.u=this.L=this.M=this.G=this.I=this.J=null;this.O={}}var TW="#define _b 8\n#define _c 8000\n#define _d "+QB+"\n#define _e 2\n#define _f 16\n#define _g 8\n#define _h vec4(0., 0., 0., 0.2)\n#define _i 2\n#define _j 9\n#define _k 6\n#define _l 3\n#define _m 0\n#define _n 1\n#define _o 2\n#define _p 4\n#define _q 5\n#define _r 12\n#define _s 0\n#define _t 8\n#define _u 2\n#define _v 1\n#define _w 22\n\n"; +SW.prototype.a=function(a,b){b="#define _a "+b.f+"\n";var c=this.O[b];c||(c=zV(a,TW+b+"precision highp float;uniform float c,o,J;uniform vec4 d,f,j,s,t,u,v;uniform sampler2D e,g;vec2 Xa(vec2 M,float N){float O=float(_r);M.y=O*M.y+N;return (M+.5)*d.zw;}vec2 Ya(vec4 M){return vec2(M.g+M.b*256.,M.a);}vec2 Za(vec2 M){vec4 N=texture2D(g,(floor(M*65535.+.5)+.5)*f.zw);N=floor(N*255.+.5);return Ya(N);}float ab(vec2 M,vec2 N){vec4 O=texture2D(e,M+N);float P,Q;P=O.r*255.*4.;Q=O.g*(255./64.);return P+Q;}\n#if _a==1\nuniform float h;varying vec3 i;\n#endif\nuniform vec3 k,l;uniform mat4 m;\n#if _a==1\nuniform mat4 p;vec3 bb(vec3 M){const float N=6371010.;float O,P,Q,R,S,T,U,V,W,X;O=M.x;P=exp(M.y);Q=P*P;R=2.*P/(1.+Q);S=(Q-1.)/(1.+Q);T=M.z*N*R;U=T+N;V=U*R*cos(O);W=U*R*sin(O);X=U*S;return vec3(V,W,X);}vec4 cb(vec3 M){vec4 N,Q;N=m*vec4(M,1);vec3 O,P;O=M;O/=o;O+=k+l;O.xy-=.5;O.y=-O.y;O*=3.141592653589793*2.;P=bb(O);Q=p*vec4(P,1);Q/=Q.w;N/=N.w;return mix(N,Q,h);}\n#else\nvec4 cb(vec3 M){return m*vec4(M,1);}\n#endif\nvec3 db(vec3 M,vec3 N){vec3 O=M-k+(N-l);return O*o;}vec3 eb(vec2 M,vec2 N,vec2 O){vec3 P,Q;P=vec3(M.x,N.x,O.x)*65535.+.5;\n#if _a==1\nP-=fract(P);\n#else\nP=floor(P);\n#endif\nP=P/65536.;P=(fract(P+.5)-.5)*4.;Q=vec3(M.y,N.y,O.y)*65535.;Q/=1073741824.;return db(P,Q);}float fb(float M){float N,O;N=1./float(_w+1);O=1.-N-j.z*N;return M*N+O;}varying vec4 w,A,B;varying vec3 x;const float L=1.;attribute vec4 C;attribute vec4 D;attribute vec4 E;attribute vec4 F;attribute vec2 G;attribute float H;uniform bool I;void main(){bool M,N,P,Q,R,S,T,U,V,W,Ha,Qa;M=true;if(H==2.)M=false;if(H==4.)M=false;if(H==5.)M=false;N=true;if(H==1.)N=false;if(H==2.)N=false;if(H==5.)N=false;float O,ba,ca,da,ea,fa,ga,ha,ia,ka,la,ma,na,oa,qa,ra,sa,ta,ua,Ba,Ea,Fa,Ga,Ia,Ja,Ka,La,Ma,Oa,Pa,Ta,Ua,Va,Wa;O=floor(F.w*255.+.5);P=fract(O*(1./4.))>=.5;Q=fract(O*(1./8.))>=.5;R=fract(O*(1./16.))>=.5;S=fract(O*(1./32.))>=.5;T=fract(O*(1./64.))>=.5;U=fract(O*(1./128.))>=.5;V=I?R:P;W=I?S:Q;vec2 X,Y,Z,aa,va,wa,xa,Aa,Na;X=Za(E.xy);Y=vec2(0,1.*d.w);Z=Xa(X,float(_k));aa=Xa(X,float(_j));ba=float(_s);w=texture2D(e,(I?aa:Z)+ba*Y);ca=float(_v);da=ab(Z,ca*Y);ea=ab(aa,ca*Y);fa=I?ea:da;ga=fa*.5;ha=da*.5;ia=float(_i);vec4 ja,Sa;ja=texture2D(e,(I?aa:Z)+ia*Y);ka=ja.r*255./float(_u);la=ja.g*255./float(_u)+ka;ma=ja.z*255.;na=floor(ma/128.);oa=-1.*na*2.+1.;ma=oa*ma+na*128.;ma=ma/float(_t);const float pa=3.141592653589793*2./256.;qa=floor(F.x*255.+.5);ra=floor(F.y*255.+.5)*.5;sa=floor(F.z*255.+.5)*.5;ta=qa+ra;ua=qa+sa;qa*=pa;ra*=pa;sa*=pa;ta*=pa;ua*=pa;va=vec2(sin(ta),-cos(ta));wa=vec2(sin(ua),-cos(ua));va/=cos(ra);wa/=cos(sa);xa=vec2(cos(qa),sin(qa));Aa=M?va:wa;Ba=tan(M?ra:sa);vec3 Ca,Da,Ra;Ca=eb(C.yx,C.wz,vec2(0));Da=eb(D.yx,D.wz,vec2(0));Ca.xy+=ma*va*1.0000001;Da.xy+=ma*wa*1.0000001;Ea=length(Da.xy-Ca.xy);if(W&&U)Ea-=ha;if(V&&T)Ea-=ha;Fa=L/c;Ga=Fa*.5;Ha=M?V:W;Ia=Ha?ga+Ga:0.;Ja=ga+Ga;Ka=M?-1.:1.;La=N?-1.:1.;x.x=M?0.:Ea;x.y=0.;x.x+=Ia*Ka;x.x+=Ja*La*Ba;x.y+=Ja*La;Ma=Ga/fa;x.xy/=Ea;x.z=float(V);x.z+=float(W)*.5;if(u.w>0.||v.w>0.)x.x=0.;B.x=-Ea/Fa;B.y=-.5*fa/Fa+.5;A=vec4(0,1,0,0);B.zw=vec2(1,0);Na=Ea*G;if(Na.x>1e6)Na.x=0.;Oa=0.;if(t.w>0.){vec2 Pa=t.zw*s.xy;float Qa=fa*Pa.x/Pa.y;ka=(la=Qa);}else if(la>0.)Oa=ka/la*.5;else ka=(la=1e6);A.xy=Na.xy;A.x+=Ia*Ka;A.x+=Ja*La*Ba;A.x+=M?0.:Ea;A.y-=Ia*Ka;A.y-=Ja*La*Ba;A.y+=M?Ea:0.;A.z=A.x/J;A.z/=la;A.xy/=fa;A.w=N?-Ma:1.+Ma;A.z-=Oa;Pa=J*.5/Fa;B.z=la*Pa;B.w=.5+(ka-la)*Pa;Qa=M?T:U;if(Ha&&Qa)Ia-=ha;Ra=M?Ca:Da;Ra.xy+=Ia*Ka*xa;Ra.xy+=Ja*La*Aa;Sa=cb(Ra);Ta=E.z;Ua=E.w;Va=I?Ua:Ta;Wa=fb(Va);gl_Position=vec4(Sa.xy/Sa.w,Wa,1);if(Sa.w<0.||t.w==0.&&w.a==0.)gl_Position=vec4(0);}", +TW+b+"precision highp float;precision highp float;\n#if _a==1\nvarying vec3 i;\n#endif\nuniform sampler2D r;uniform vec4 s,t,u,v;varying vec4 w,A,B;varying vec3 x;const float K=1.;float ca(float L){const float M=0.;const float N=1.;const float O=.3;const float P=.3;const float Q=2.*M-2.*N+O+P;const float R=3.*N-3.*M-2.*O-P;const float S=O;const float T=M;return clamp(((Q*L+R)*L+S)*L+T,0.,1.);}void main(){vec2 L=vec2(x.x-clamp(x.x,0.,1.),x.y);float M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z;M=L.x*L.x+L.y*L.y;N=A.z;O=B.z;P=B.w;N=abs(fract(N)*2.-1.);Q=clamp(O*N+P,0.,1.);R=x.z;S=float(L.x<0.)*floor(R);T=float(L.x>0.)*fract(R)*2.;Q=clamp(Q+S+T,0.,1.);U=B.x;V=B.y;W=sqrt(M)*U;X=clamp(W-V+1.,0.,1.);Y=clamp(W+V,0.,1.);if(K>1.){X=ca(X);Y=ca(Y);}Z=clamp(X-Y,0.,1.);Z*=Q;if(Z==0.)discard;if(t.w>0.){float aa=fract(A.z);gl_FragColor=texture2D(r,t.xy+vec2(aa,A.w)*t.zw);}else{gl_FragColor=w;gl_FragColor.rgb*=gl_FragColor.a;gl_FragColor*=Z;}if(v.w>0.&&A.y<.5){vec2 aa=vec2(A.w,.5-A.y)*v.zw;aa.y=max(aa.y,.5*s.w);vec4 ba=texture2D(r,v.xy+aa);gl_FragColor*=ba.a;}else if(u.w>0.){vec2 aa=vec2(A.w,.5-min(.5,A.x))*u.zw;aa.y=max(aa.y,.5*s.w);vec4 ba=texture2D(r,u.xy+aa);gl_FragColor*=ba.a;}}", +"CDEFGH".split("")),this.O[b]=c);this.g=c}; +SW.prototype.bind=function(a,b){this.a(a,b);if(this.C!=this.g){var c=this.g,d=function(b){return a.getUniformLocation(c,b)};this.J=d("a");this.I=d("b");this.G=d("c");this.M=d("d");this.L=d("e");this.u=d("f");this.s=d("g");this.K=d("h");this.i=d("j");this.j=d("k");this.l=d("l");this.m=d("m");this.o=d("n");this.H=d("o");this.D=d("p");this.B=d("q");this.v=d("r");this.A=d("s");this.c=d("t");this.f=d("u");this.b=d("v");this.Hb=d("I");this.h=d("J");this.C=this.g}a.useProgram(this.C);this.J&&a.uniform4fv(this.J, +b.s.value);this.I&&a.uniform4fv(this.I,b.o.value);this.G&&a.uniform1f(this.G,b.b.value);this.M&&a.uniform4fv(this.M,b.B.value);this.L&&a.uniform1i(this.L,b.A.value);this.u&&a.uniform4fv(this.u,b.v.value);this.s&&a.uniform1i(this.s,b.u.value);this.K&&a.uniform1f(this.K,b.c.value);this.i&&a.uniform4fv(this.i,b.C.value);this.j&&a.uniform3fv(this.j,b.g.value);this.l&&a.uniform3fv(this.l,b.h.value);this.m&&a.uniformMatrix4fv(this.m,!1,b.i.value);this.o&&a.uniform1f(this.o,b.j.value);this.H&&a.uniform1f(this.H, +b.m.value);this.D&&a.uniformMatrix4fv(this.D,!1,b.a.value);this.B&&a.uniform1i(this.B,b.l.value);this.v&&a.uniform1i(this.v,b.D.value);this.A&&a.uniform4fv(this.A,b.G.value);this.c&&a.uniform4fv(this.c,b.rb.value);this.f&&a.uniform4fv(this.f,b.sb.value);this.b&&a.uniform4fv(this.b,b.ib.value);this.Hb&&a.uniform1i(this.Hb,b.Hb.value);this.h&&a.uniform1f(this.h,b.Za.value)};function UW(a,b,c){this.f=a;this.h=b;this.g=yV(a,SW);this.a=new EW(!0);this.i=new ir(a,this.a.f.a,this.a.f.b,void 0);this.j=HV(a,[0,2,1,3,4,5]);this.c=c} +function VW(a,b,c){for(var d=a.f,e=a.h,f=a.a.f,g=a.j,h=a.g,k=!1,l=0;l<b.length;l++){var m=b[l],n=b[l].b;if(m.a.G||n&&n.a.G){k=!0;break}}if(k){TV(d,c,3==c.s?2:4,3,2,2,2);fr(a.c,5);e.D.set(5);k=a.c.c;n=a.c.a;e.G.set(k,n,1/k,1/n);FV(d,f);LV(d,g,f);g=hq(d);h.bind(g,e);g.uniform4f(h.c,0,0,0,0);g.uniform4f(h.f,0,0,0,0);g.uniform4f(h.b,0,0,0,0);var p=!0;for(l=0;l<b.length;l++){m=b[l];var q=m.a;if(m.b){e=m.b.a;m=e.G;var t=e.ja;e=q.G;var v=q.ja}else m=q.G,t=q.ja,v=e=null;if(m||e){g.uniform4f(h.i,q.g,q.h,q.m, +q.b);g.uniform1f(h.h,Math.pow(2,(c.zoom-q.m+100)%.25));SV(d,c,q.Z,q.g,q.h,q.b);var u=q.A;q=q.a;for(var w=Math.floor(c.zoom),y=new pq(0,0,0,0),A=0;1>=A;A++){g.uniform1f(h.Hb,A);for(var z=0;1>=z;z++){var C=0==z?m:e;if(C)for(var I=0==z?t:v,S=0;S<C.length;S++){var ca=I[S];-1!=ca&&u?(p=RW(u,ca,A,w,"stamp",q)||y,g.uniform4f(h.c,p.left/k,p.top/n,p.width/k,p.height/n),p=RW(u,ca,A,w,"startcap",q)||y,g.uniform4f(h.f,p.left/k,p.top/n,p.width/k,p.height/n),p=RW(u,ca,A,w,"endcap",q)||y,g.uniform4f(h.b,p.left/ +k,p.top/n,p.width/k,p.height/n),p=!1):p||(g.uniform4f(h.c,0,0,0,0),g.uniform4f(h.f,0,0,0,0),g.uniform4f(h.b,0,0,0,0),p=!0);OV(d,f,C[S],null)}}}}}iq(d);GV(d,f);gr(a.c)}}function WW(a,b,c){if(0!=a.a.a){var d=b.a;b=b.data;var e=PV(a.i,a.a.b,a.a.a);jO(d.a,e);d.G||(d.G=[],d.ja=[]);d.G.push(e.a[0]);d.ja.push(c);a.a.reset(d.g,d.h,d.b,b.c)}} +UW.prototype.b=function(a,b){var c=a.a,d=a.data,e=d.a;if(!e)return 2;var f=Ey(e)&&jy(Fy(e)),g=Gy(e)&&ly(Hy(e));if(!f&&!g||c.I)return 2;f=-1;g=d.b;this.a.reset(c.g,c.h,c.b,d.c);var h=c.a;d=c.f;c=c.A;a.data.getZoom();c&&0==c.a&&c.Na(h);if(Ey(e)){h=Fy(e).a;var k=g.a[1];for(c=0;c<h.length;c++){var l=k[c].ka(),m=d.a[l];l=0<CK(d,l).o?m:-1;l!=f&&(WW(this,a,f),f=l);l=a;m=h[c];var n=k[c],p=b,q=l.a,t=q.f;q=q.c;var v=n.ka();t=CK(t,v);16>=l.data.c&&Xz(t,l.data.getZoom())||(t=this.a,FW(t,Vw(m),Ww(m)),t.D=0,GW(t, +ZV(q,v)),t.o=65535-n.b|65535-n.za<<16,n=rI(l.data.getZoom(),p),FI(m,t,l.data.getZoom(),n))}}WW(this,a,f);f=-1;if(Gy(e))for(b=Hy(e).a,e=g.a[2],c=0;c<b.length;c++)l=a,k=b[c],g=e[c],d=l.a,m=d.f,d=d.c,h=g.ka(),m=CK(m,h),l=l.data.getZoom(),Xz(m,l)||1>m.c||0>=uA(m,0,l)||tA(m,0,l)&0||null==k.a||null==k.f||!k.f||(k=ux(k),l=this.a,FW(l,1,1),GW(l,ZV(d,h)),l.o=65535-(g.za+1)|65535-(g.za+2)<<16,II(k,l));WW(this,a,f);return 2};function XW(){this.o=this.c=this.outline=this.b=this.m=this.s=this.v=this.i=this.h=this.g=this.f=this.H=this.C=this.j=this.l=this.D=this.G=this.u=this.A=this.B=null;this.I={}}var YW="#define _b 8\n#define _c 8000\n#define _d "+QB+"\n#define _e 2\n#define _f 16\n#define _g 8\n#define _h vec4(0., 0., 0., 0.2)\n#define _i 2\n#define _j 9\n#define _k 6\n#define _l 3\n#define _m 0\n#define _n 1\n#define _o 2\n#define _p 4\n#define _q 5\n#define _r 12\n#define _s 0\n#define _t 8\n#define _u 2\n#define _v 1\n#define _w 22\n\n"; +XW.prototype.a=function(a,b){b="#define _a "+b.f+"\n";var c=this.I[b];c||(c=zV(a,YW+b+"precision highp float;uniform vec4 a,d,f;uniform sampler2D e,g;vec2 qa(vec2 F,float G){float H=float(_r);F.y=H*F.y+G;return (F+.5)*d.zw;}vec2 ra(vec4 F){return vec2(F.g+F.b*256.,F.a);}float sa(vec2 F,vec2 G){vec4 H=texture2D(e,F+G);float I,J;I=H.r*255.*4.;J=H.g*(255./64.);return I+J;}float ta(float F){return mod(F,32.)/31.;}void ua(vec2 F,out float G,out vec2 H,out bool I){vec4 J=texture2D(g,(floor(F*65535.+.5)+.5)*f.zw);J=floor(J*255.+.5);G=ta(J.r);I=mod(J.r/32.,2.)>=1.;H=ra(J);}\n#if _a==1\nuniform float h;varying vec3 i;\n#endif\nuniform vec3 k,l;uniform mat4 m;uniform float o,C;\n#if _a==1\nuniform mat4 p;vec3 va(vec3 F){const float G=6371010.;float H,I,J,K,L,M,N,O,P,Q;H=F.x;I=exp(F.y);J=I*I;K=2.*I/(1.+J);L=(J-1.)/(1.+J);M=F.z*G*K;N=M+G;O=N*K*cos(H);P=N*K*sin(H);Q=N*L;return vec3(O,P,Q);}vec4 wa(vec3 F){vec4 G,J;G=m*vec4(F,1);vec3 H,I;H=F;H/=o;H+=k+l;H.xy-=.5;H.y=-H.y;H*=3.141592653589793*2.;I=va(H);J=p*vec4(I,1);J/=J.w;G/=G.w;return mix(G,J,h);}\n#else\nvec4 wa(vec3 F){return m*vec4(F,1);}\n#endif\nvec3 xa(vec3 F,vec3 G){vec3 H=F-k+(G-l);return H*o;}vec3 Aa(vec2 F,vec2 G,vec2 H){vec3 I,J;I=vec3(F.x,G.x,H.x)*65535.+.5;\n#if _a==1\nI-=fract(I);\n#else\nI=floor(I);\n#endif\nI=I/65536.;I=(fract(I+.5)-.5)*4.;J=vec3(F.y,G.y,H.y)*65535.;J/=1073741824.;return xa(I,J);}uniform bool q,D;varying vec4 r,s,t;attribute vec2 u;attribute vec4 v;attribute vec4 w;attribute vec4 x;attribute vec4 A;attribute vec4 B;void main(){vec2 F,G,I,L,X,aa,ia,ka,la,ma;F=a.xy*.5;G=2.*a.zw;float H,K,M,N,O,P,Q,R,S,ba,ca,ea,fa,ga,ha,na,oa,pa;bool J;ua(x.zw,H,I,J);K=float(_o);L=qa(I,K);M=sa(L,vec2(0))*float(D);N=floor(A.w*32767.+.5)/float(_f);O=floor(B.x*32767.+.5)/float(_f);P=floor(B.y*32767.+.5)/float(_f);Q=floor(B.w*32767.+.5);R=1.;if(Q<=1.)R=-1.;S=1.;if(Q==1.)S=-1.;if(Q==2.)S=-1.;vec3 T,U,V,Y,da;T=Aa(v.yx,v.wz,x.yx);U=Aa(w.yx,w.wz,x.yx);V=R==-1.?T:U;vec4 W,Z,ja;W=wa(V);X=F*W.xy/W.w;Y=R==-1.?U:T;Z=wa(Y);aa=F*Z.xy/Z.w;ba=length(aa.xy-X.xy);ca=N<0.?N-M:N+M;da=floor(A.xyz*32767.+.5)/float(_c);ea=floor(B.z*32767.+.5)/float(_f);fa=ba*u.x-O;fa+=ca*da.z;ga=fa+ba;ga+=ca*(da.x+da.y);ha=R<0.?fa-ea:ga+ea;ia=vec2(0,P);ia+=vec2(-M,M);r=vec4(ha,ia,ea);ja=vec4(X,aa);ka=normalize(aa-X);la=vec2(-ka.y,ka.x);ma=R==1.?da.yx:da.xy;ja+=la.xyxy*ca*R;ja+=vec4(-ma.xx,ma.yy)*ka.xyxy*ca;s=R<0.?ja:ja.zwxy;s+=F.xyxy;X=ja.xy;X-=ea*ka;X+=(ea+1.)*la*S*R;na=u.y;gl_Position=vec4(X*G,na,1);oa=step(W.w,1e-4)+step(Z.w,1e-4);pa=min(1.,oa+float(q)*step(ba,P));gl_Position.xy*=1.-pa;gl_Position.xy*=sign(H);t=texture2D(e,qa(I,C));t.a*=H;gl_Position.xy*=sign(t.a);}", +YW+b+"precision highp float;uniform float c;precision highp float;\n#if _a==1\nvarying vec3 i;\n#endif\nprecision highp float;varying vec4 r,s,t;void main(){float E,G,K,M,N;E=r.x;vec2 F,H,I,J,L;F=r.yz;G=1.-max(max(F.x-E,E-F.y)*c,0.);if(G<=0.)discard;H=gl_FragCoord.xy/c;I=H-s.xy;J=s.zw-s.xy;K=clamp(dot(I,J)/dot(J,J),0.,1.);L=H-mix(s.xy,s.zw,K);M=dot(L,L);N=sqrt(M)-r.w;vec4 O=t;O.a=G*clamp(.5-N*c,0.,1.);if(O.a==0.)discard;gl_FragColor=O;}","uvwxAB".split("")),this.I[b]=c);this.c=c}; +XW.prototype.bind=function(a,b){this.a(a,b);if(this.o!=this.c){var c=this.c,d=function(b){return a.getUniformLocation(c,b)};this.B=d("a");this.A=d("b");this.u=d("c");this.G=d("d");this.D=d("e");this.l=d("f");this.j=d("g");this.C=d("h");this.H=d("j");this.f=d("k");this.g=d("l");this.h=d("m");this.i=d("n");this.v=d("o");this.s=d("p");this.m=d("q");this.b=d("C");this.outline=d("D");this.o=this.c}a.useProgram(this.o);this.B&&a.uniform4fv(this.B,b.s.value);this.A&&a.uniform4fv(this.A,b.o.value);this.u&& +a.uniform1f(this.u,b.b.value);this.G&&a.uniform4fv(this.G,b.B.value);this.D&&a.uniform1i(this.D,b.A.value);this.l&&a.uniform4fv(this.l,b.v.value);this.j&&a.uniform1i(this.j,b.u.value);this.C&&a.uniform1f(this.C,b.c.value);this.H&&a.uniform4fv(this.H,b.C.value);this.f&&a.uniform3fv(this.f,b.g.value);this.g&&a.uniform3fv(this.g,b.h.value);this.h&&a.uniformMatrix4fv(this.h,!1,b.i.value);this.i&&a.uniform1f(this.i,b.j.value);this.v&&a.uniform1f(this.v,b.m.value);this.s&&a.uniformMatrix4fv(this.s,!1,b.a.value); +this.m&&a.uniform1i(this.m,b.l.value);this.b&&a.uniform1f(this.b,b.Sa.value);this.outline&&a.uniform1i(this.outline,b.outline.value)};function ZW(a,b){this.c=a;this.g=b;this.f=yV(a,XW);this.a=new EV(6,[[2,5126],[4,5123],[4,5123],[4,5123],[4,5122],[4,5122]]);this.h=new ir(a,this.a.a,this.a.b,65536)} +function $W(a,b,c,d){for(var e=a.c,f=a.g,g=a.a,h=a.f,k=!1,l=0;l<b.length;++l){var m=b[l];if(m.b&&m.b.a.T[d]){k=!0;break}if(m.a.T[d]){k=!0;break}}if(k){TV(e,c,3,3,1,2,1);FV(e,g);c=hq(e);h.bind(c,f);for(l=0;l<b.length;++l)if(b[l].b?(f=b[l].b.a.T[d],k=b[l].a.T[d]):(f=b[l].a.T[d],k=null),f||k)c.uniform1f(h.b,1),c.uniform1f(h.outline,1),NV(e,a.a,f,k),c.uniform1f(h.b,0),c.uniform1f(h.outline,0),NV(e,a.a,f,k);iq(e);GV(e,g)}} +ZW.prototype.b=function(a,b){a=a.a;var c=a.c,d=this.a.f,e=b.a;if(!e.length)return 2;for(var f=0,g=0;g<e.length;++g){var h=e[g],k=h.label.a.a-1;f+=k*this.a.h}var l=[0,1,2,0,2,3];f=new Uint32Array(f);var m=new Float32Array(f.buffer),n=0;for(g=0;g<e.length;++g){h=e[g];var p=h.label.a,q=ZV(c,h.a);k=p.a-1;var t=0!=h.f?eL(p,k):0,v=SK(p.b,p.f),u=0;0<=t&&(1==p.h?u=t/2:3==p.h&&(u=t));var w=pI(p.altitude,a.b,0);q=oI(q.x,q.y);for(var y=oI(16*h.b,16*h.width),A=0,z=0,C=0;C<k;++C){var I=pI(gL(p,C),a.b,a.g),S=pI(hL(p, +C),a.b,a.h),ca=pI(gL(p,C+1),a.b,a.g),Z=pI(hL(p,C+1),a.b,a.h),ha=0,ea=0;0!=h.f&&(ha=p.i[C],ea=p.i[C+1],0==C&&0>t&&(ha=-t/2),C==k-1&&0>t&&(ea=-t/2));for(var ja=SK(p.b,C+1)-SK(p.b,C),Y=ja?(A-v)/ja:0,ma=oI(8E3*Yn(ha,-4,4),8E3*Yn(ea,-4,4)),Ga=oI(8E3*Yn(z-u,-4,4),16*h.f),wa=0;6>wa;wa++){var Kd=oI(16*(h.height+3)/2,l[wa]);m[n+0]=Y;m[n+1]=tW(h);f[n+2]=I;f[n+3]=S;f[n+4]=ca;f[n+5]=Z;f[n+6]=w;f[n+7]=q;f[n+8]=ma;f[n+9]=Ga;f[n+10]=y;f[n+11]=Kd;n+=d}A+=ja;z+=ha+ea}}n&&(c=a.a,d=PV(this.h,f),jO(c,d),a.T[b.b]=d.a[0]); +return 2};var aX=0,bX={};function cX(a){a=(bX[a]||null).b;return new pq(a.left/2+2,a.top/2+2,a.width/2-4,a.height/2-4)}function dX(){this.b=this.a=this.data=null};function eX(){this.A=this.g=this.b=this.K=this.J=this.u=this.text=this.c=this.f=this.O=this.v=this.B=this.D=this.m=this.l=this.j=this.i=this.h=this.I=this.o=this.s=this.L=this.M=this.C=this.G=this.H=null;this.P={}}var fX="#define _b 8\n#define _c 8000\n#define _d "+QB+"\n#define _e 2\n#define _f 16\n#define _g 8\n#define _h vec4(0., 0., 0., 0.2)\n#define _i 2\n#define _j 9\n#define _k 6\n#define _l 3\n#define _m 0\n#define _n 1\n#define _o 2\n#define _p 4\n#define _q 5\n#define _r 12\n#define _s 0\n#define _t 8\n#define _u 2\n#define _v 1\n#define _w 22\n#define _x 2\n\n"; +eX.prototype.a=function(a,b){b="#define _a "+b.f+"\n";var c=this.P[b];c||(c=zV(a,fX+b+"precision highp float;uniform vec4 d,f;uniform sampler2D e,g;vec2 xa(vec2 K,float L){float M=float(_r);K.y=M*K.y+L;return (K+.5)*d.zw;}vec2 Aa(vec4 K){return vec2(K.g+K.b*256.,K.a);}float Ba(float K){return mod(K,32.)/31.;}void Ca(vec2 K,out float L,out vec2 M,out bool N){vec4 O=texture2D(g,(floor(K*65535.+.5)+.5)*f.zw);O=floor(O*255.+.5);L=Ba(O.r);N=mod(O.r/32.,2.)>=1.;M=Aa(O);}\n#if _a==1\nuniform float h;varying vec3 i;\n#endif\nuniform vec3 k,l;uniform mat4 m;uniform float o,F,G;\n#if _a==1\nuniform mat4 p;vec3 Da(vec3 K){const float L=6371010.;float M,N,O,P,Q,R,S,T,U,V;M=K.x;N=exp(K.y);O=N*N;P=2.*N/(1.+O);Q=(O-1.)/(1.+O);R=K.z*L*P;S=R+L;T=S*P*cos(M);U=S*P*sin(M);V=S*Q;return vec3(T,U,V);}vec4 Ea(vec3 K){vec4 L,O;L=m*vec4(K,1);vec3 M,N;M=K;M/=o;M+=k+l;M.xy-=.5;M.y=-M.y;M*=3.141592653589793*2.;N=Da(M);O=p*vec4(N,1);O/=O.w;L/=L.w;return mix(L,O,h);}\n#else\nvec4 Ea(vec3 K){return m*vec4(K,1);}\n#endif\nvec3 Fa(vec3 K,vec3 L){vec3 M=K-k+(L-l);return M*o;}vec3 Ga(vec2 K,vec2 L,vec2 M){vec3 N,O;N=vec3(K.x,L.x,M.x)*65535.+.5;\n#if _a==1\nN-=fract(N);\n#else\nN=floor(N);\n#endif\nN=N/65536.;N=(fract(N+.5)-.5)*4.;O=vec3(K.y,L.y,M.y)*65535.;O/=1073741824.;return Fa(N,O);}const float I=float(_x);const float J=1./float(_f);varying vec2 s;varying vec4 t,u;attribute vec2 v;attribute vec4 w;attribute vec4 x;attribute vec4 A;attribute vec4 B;attribute vec4 C;attribute vec2 D;attribute vec4 E;void main(){bool K,O,T,Y,pa;float L,R,S,U,W,X,Z,aa,ba,ca,da,ea,fa,ga,ha,ma,na,oa,qa,ta,ua,va,wa;vec2 M,N,ia,ja,sa;Ca(A.zw,L,M,K);N=xa(M,F);u=texture2D(e,N);u.a*=L;O=false;if(L<=0.)O=true;vec3 P,Q,V,ka,la;P=Ga(w.yx,w.wz,A.yx);Q=Ga(x.yx,x.wz,A.yx);R=length(P.xy-Q.xy);S=floor(B.w*32767.+.5)/float(_f);T=E.y>0.;U=K&&T?-S:S;V=floor(B.xyz*32767.+.5)/float(_c);W=floor(D.x*32767.+.5)/float(_f);X=floor(D.y*32767.+.5)/float(_f);Y=E.x>0.;W=K&&Y?W*-1.-X:W;Z=v.x*R-W;Z+=U*V.z;aa=R+U*(V.x+V.y);ba=Z+aa;Z+=.001;ba+=.001;ca=max(Z,0.);da=min(ba,X);ea=(ca-Z)/aa;fa=(da-Z)/aa;ga=K?X-da:ca;ha=K?X-ca:da;if(ga>ha)O=true;ia=normalize(Q.xy-P.xy);ja=vec2(-ia.y,ia.x);P.xy-=U*V.x*ia;P.xy+=U*ja;Q.xy+=U*V.y*ia;Q.xy+=U*ja;ka=mix(P,Q,ea);la=mix(P,Q,fa);ma=floor(C.x*65535.+.5)*J;na=floor(C.y*65535.+.5)*J+G+1.;oa=floor(E.z*255.+.5);pa=true;if(oa==2.)pa=false;if(oa==3.)pa=false;qa=1.;if(oa==0.)qa=-1.;if(oa==3.)qa=-1.;ka.xy-=ma*ia;la.xy+=ma*ia;ka.xy+=na*qa*ja;la.xy+=na*qa*ja;vec4 ra=Ea(pa?ka:la);gl_Position=vec4(ra.xy/ra.w,v.y,1);sa=vec2(ga-ma,ha+ma);if(K)sa=sa.yx;ta=pa?sa.x:sa.y;ua=(K?qa:-qa)*na;va=floor(C.z*65535.+.5);wa=floor(C.w*65535.+.5);t.x=va+ta*I;t.y=ua*I;t.z=wa+.5;t.w=wa+1.5;s.x=va+ga*I;s.y=va+ha*I;if(O)gl_Position=vec4(0);}", +fX+b+"precision highp float;precision highp float;\n#if _a==1\nvarying vec3 i;\n#endif\nconst float M=float(_x);const float N=1./float(_f);uniform vec4 r,J;varying vec2 s;varying vec4 t,u;precision highp float;uniform sampler2D H,I;uniform vec2 K,L;void main(){float O,Y;O=floor(t.x)+.5;vec4 P,Q,S;P=texture2D(H,vec2(O,t.z)*r.zw);Q=texture2D(H,vec2(O,t.w)*r.zw);vec2 R,T,U,V,W,X;R=vec2(P.r*255.+P.g*(255./256.),P.b*255.+P.a*(255./256.));R=R-128.;R+=O-t.x;S=Q*J.xyxy+J.zwzw;T=vec2(-R.x,-t.y);U=vec2(-R.y,-t.y);V=S.xy+T*K;W=S.zw+U*K;X=vec2(texture2D(I,V).a,texture2D(I,W).a);X=X*L.x+L.y;if(R.x+t.x<s.x)X.x=0.;if(R.x+t.x>s.y)X.x=0.;if(R.y+t.x<s.x)X.y=0.;if(R.y+t.x>s.y)X.y=0.;if(P.x==0.)X.x=0.;if(P.z==0.)X.y=0.;Y=clamp(max(X.x,X.y),0.,1.);gl_FragColor=vec4(u.r,u.g,u.b,u.a*Y);if(Y==0.)discard;}", +"vwxABCDE".split("")),this.P[b]=c);this.g=c}; +eX.prototype.bind=function(a,b){this.a(a,b);if(this.A!=this.g){var c=this.g,d=function(b){return a.getUniformLocation(c,b)};this.H=d("a");this.G=d("b");this.C=d("c");this.M=d("d");this.L=d("e");this.s=d("f");this.o=d("g");this.I=d("h");this.h=d("j");this.i=d("k");this.j=d("l");this.l=d("m");this.m=d("n");this.D=d("o");this.B=d("p");this.v=d("q");this.O=d("r");this.f=d("F");this.c=d("G");this.text=d("H");this.u=d("I");this.J=d("J");this.K=d("K");this.b=d("L");this.A=this.g}a.useProgram(this.A);this.H&& +a.uniform4fv(this.H,b.s.value);this.G&&a.uniform4fv(this.G,b.o.value);this.C&&a.uniform1f(this.C,b.b.value);this.M&&a.uniform4fv(this.M,b.B.value);this.L&&a.uniform1i(this.L,b.A.value);this.s&&a.uniform4fv(this.s,b.v.value);this.o&&a.uniform1i(this.o,b.u.value);this.I&&a.uniform1f(this.I,b.c.value);this.h&&a.uniform4fv(this.h,b.C.value);this.i&&a.uniform3fv(this.i,b.g.value);this.j&&a.uniform3fv(this.j,b.h.value);this.l&&a.uniformMatrix4fv(this.l,!1,b.i.value);this.m&&a.uniform1f(this.m,b.j.value); +this.D&&a.uniform1f(this.D,b.m.value);this.B&&a.uniformMatrix4fv(this.B,!1,b.a.value);this.v&&a.uniform1i(this.v,b.l.value);this.O&&a.uniform4fv(this.O,b.Wa.value);this.f&&a.uniform1f(this.f,b.Sa.value);this.c&&a.uniform1f(this.c,b.jb.value);this.text&&a.uniform1i(this.text,b.text.value);this.u&&a.uniform1i(this.u,b.Ba.value);this.J&&a.uniform4fv(this.J,b.Qa.value);this.K&&a.uniform2fv(this.K,b.Ra.value);this.b&&a.uniform2fv(this.b,b.$a.value)};function gX(a,b,c,d){this.h=a;this.c=b;this.i=yV(a,eX);this.a=new EV(6,[[2,5126],[4,5123],[4,5123],[4,5123],[4,5122],[4,5123],[2,5122],[4,5121]]);this.j=new ir(a,this.a.a,this.a.b,65536);this.g=c;this.f=d} +function hX(a,b,c,d){for(var e=a.h,f=a.c,g=a.a,h=a.i,k=!1,l=0;l<b.length;++l){var m=b[l];if(m.b&&m.b.a.U[d]){k=!0;break}if(m.a.U[d]){k=!0;break}}if(k){TV(e,c,3,3,1,2,1);l=a.c;k=a.g;fr(k,4);l.text.set(4);l.Wa.set(k.c,k.a,1/k.c,1/k.a);l=a.c;k=a.f;m=k.c;var n=k.a;fr(k,5);l.Ba.set(5);l.Ra.set(1/m,1/n);l.Qa.set(2040/m,3060/n,4/m,6/n);FV(e,g);l=c.l;c=10.625*l;k=-.5*c+.5;m=k+1.5*l;n=hq(e);h.bind(n,f);for(l=0;l<b.length;++l){if(b[l].b){f=b[l].b.a.U[d];var p=b[l].a.U[d]}else f=b[l].a.U[d],p=null;if(f||p){var q= +b[l].a;n.uniform4f(h.h,q.g,q.h,q.m,q.b);n.uniform1f(h.f,5);n.uniform1f(h.c,1.5);n.uniform2f(h.b,c,m);NV(e,g,f,p);n.uniform1f(h.f,4);n.uniform1f(h.c,0);n.uniform2f(h.b,c,k);NV(e,g,f,p)}}iq(e);GV(e,g);gr(a.g);gr(a.f)}} +gX.prototype.b=function(a,b){a=a.a;var c=a.c,d=b.a;if(!d.length)return 2;for(var e=0,f=0;f<d.length;++f){var g=d[f],h=g.label.a.a-1;e+=h*this.a.h}var k=[0,1,2,0,2,3];e=new Uint32Array(e);var l=new Float32Array(e.buffer),m=0;for(f=0;f<d.length;++f){g=d[f];var n=g.label.a,p=g.c;h=ZV(c,g.a);var q=tW(g),t=g.g?1:0,v=1==n.h?1:0,u=pI(n.altitude,a.b,0),w=oI(p.f/2*16,(p.height-2)/2*16),y=oI(p.a,p.b);p=oI(16*g.b,16*p.width);var A=oI(h.x,h.y),z=0!=g.f?eL(n,n.a-1):0,C=SK(n.b,n.f),I=0;0<=z&&(1==n.h?I=z/2:3==n.h&& +(I=z));var S=0,ca=0;h=n.a-1;for(var Z=0;Z<h;Z++){var ha=pI(gL(n,Z),a.b,a.g),ea=pI(hL(n,Z),a.b,a.h),ja=pI(gL(n,Z+1),a.b,a.g),Y=pI(hL(n,Z+1),a.b,a.h),ma=0,Ga=0;0!=g.f&&(ma=n.i[Z],Ga=n.i[Z+1],0==Z&&0>z&&(ma=-z/2),Z==h-1&&0>z&&(Ga=-z/2));for(var wa=SK(n.b,Z+1)-SK(n.b,Z),Kd=wa?(S-C)/wa:0,xy=oI(8E3*Yn(ma,-4,4),8E3*Yn(Ga,-4,4)),qj=oI(8E3*Yn(ca-I,-4,4),16*g.f),rj=0;rj<k.length;rj++){var yy=(v&255|(t&255)<<8|(k[rj]&255)<<16|0)>>>0;l[m+0]=Kd;l[m+1]=q;e[m+2]=ha;e[m+3]=ea;e[m+4]=ja;e[m+5]=Y;e[m+6]=u;e[m+7]=A; +e[m+8]=xy;e[m+9]=qj;e[m+10]=w;e[m+11]=y;e[m+12]=p;e[m+13]=yy;m+=this.a.f}S+=wa;ca+=ma+Ga}}m&&(c=PV(this.j,e),jO(a.a,c),a.U[b.b]=c.a[0]);return 2};function iX(){this.u=this.b=this.G=this.D=this.s=this.B=this.c=this.la=this.o=this.v=this.C=this.j=this.i=this.h=this.g=this.f=this.J=this.l=this.m=this.K=this.L=this.A=this.H=this.I=null;this.M={}}var jX="#define _b 8\n#define _c 8000\n#define _d "+QB+"\n#define _e 2\n#define _f 16\n#define _g 8\n#define _h vec4(0., 0., 0., 0.2)\n#define _i 2\n#define _j 9\n#define _k 6\n#define _l 3\n#define _m 0\n#define _n 1\n#define _o 2\n#define _p 4\n#define _q 5\n#define _r 12\n#define _s 0\n#define _t 8\n#define _u 2\n#define _v 1\n#define _w 22\n\n"; +iX.prototype.a=function(a,b){b="#define _a "+b.f+"\n";var c=this.M[b];c||(c=zV(a,jX+b+"precision highp float;uniform vec4 a,b,d,f;vec2 S(vec2 G){return (G*b.xy+b.xy)*.5;}vec2 T(vec2 G){return (G*b.zw-vec2(.5))*2.;}uniform sampler2D e,g;vec2 U(vec2 G,float H){float I=float(_r);G.y=I*G.y+H;return (G+.5)*d.zw;}vec2 V(vec4 G){return vec2(G.g+G.b*256.,G.a);}float W(float G){return mod(G,32.)/31.;}void X(vec2 G,out float H,out vec2 I){vec4 J=texture2D(g,(floor(G*65535.+.5)+.5)*f.zw);J=floor(J*255.+.5);H=W(J.r);I=V(J);}\n#if _a==1\nuniform float h;varying vec3 i;\n#endif\nuniform vec3 k,l;uniform mat4 m;uniform float n,o,w,D,E;\n#if _a==1\nuniform mat4 p;vec3 Y(vec3 G){const float H=6371010.;float I,J,K,L,M,N,O,P,Q,R;I=G.x;J=exp(G.y);K=J*J;L=2.*J/(1.+K);M=(K-1.)/(1.+K);N=G.z*H*L;O=N+H;P=O*L*cos(I);Q=O*L*sin(I);R=O*M;return vec3(P,Q,R);}vec4 Z(vec3 G){vec4 H,K;H=m*vec4(G,1);vec3 I,J;I=G;I/=o;I+=k+l;I.xy-=.5;I.y=-I.y;I*=3.141592653589793*2.;J=Y(I);K=p*vec4(J,1);K/=K.w;H/=H.w;return mix(H,K,h);}\n#else\nvec4 Z(vec3 G){return m*vec4(G,1);}\n#endif\nvec3 aa(vec3 G,vec3 H){vec3 I=G-k+(H-l);return I*o;}vec3 ba(vec2 G,vec2 H,vec2 I){vec3 J,K;J=vec3(G.x,H.x,I.x)*65535.+.5;\n#if _a==1\nJ-=fract(J);\n#else\nJ=floor(J);\n#endif\nJ=J/65536.;J=(fract(J+.5)-.5)*4.;K=vec3(G.y,H.y,I.y)*65535.;K/=1073741824.;return aa(J,K);}vec4 ca(vec2 G,vec2 H,vec2 I){vec3 J=ba(G,H,I);return Z(J);}varying vec2 r;varying vec4 s,t;varying float u;attribute vec4 x;attribute vec4 A;attribute vec2 B;attribute vec4 C;void main(){vec2 G,H,J,K;G=A.zw;H=floor(C.xy*32767.+.5)*(1./float(_f));r=floor(C.zw*32767.+.5);vec4 I=ca(x.yx,x.wz,A.yx);J=S(I.xy/I.w);J+=vec2(H.x,-H.y)*w;J=mix(J,floor(J+.5),D);gl_Position.xy=T(J);gl_Position.z=B.x;gl_Position.w=1.;float L,N;X(G,L,K);s=texture2D(e,U(K,float(_q)));t=texture2D(e,U(K,float(_p)));s.a*=L;t.a*=L;u=dot(s.rgb,vec3(.2126,.7152,.0722));vec3 M=vec3(mix(1.6,1.,u));s.rgb=pow(s.rgb,M);t.rgb=pow(t.rgb,M);if(B.y!=0.)gl_Position.y+=sin(n)*E/a.y;N=L*I.w;if(N<=0.)gl_Position=vec4(0);}", +jX+b+"precision highp float;precision highp float;\n#if _a==1\nvarying vec3 i;\n#endif\nprecision highp float;varying vec2 r;varying vec4 s,t;varying float u;uniform float v;uniform sampler2D F;uniform vec4 G;void main(){vec2 H,K,L;H=r*G.zw;float I,J;I=texture2D(F,H).a;J=I;K=vec2(G.z*v,0);L=vec2(0,G.w*v);const float M=.9717;const float N=.5454;J+=N*texture2D(F,H-K-L).a+M*texture2D(F,H-K).a+N*texture2D(F,H-K+L).a+M*texture2D(F,H-L).a+M*texture2D(F,H+L).a+N*texture2D(F,H+K-L).a+M*texture2D(F,H+K).a+N*texture2D(F,H+K+L).a;J=min(J,1.);J*=s.a;I*=t.a;vec4 O=mix(vec4(s.rgb*J,J),vec4(t.rgb,1),I);if(O.a==0.)discard;O.rgb/=O.a;vec3 P=vec3(1./mix(1.6,1.,u));O.rgb=pow(O.rgb,P);gl_FragColor=O;}", +["x","A","B","C"]),this.M[b]=c);this.b=c}; +iX.prototype.bind=function(a,b){this.a(a,b);if(this.u!=this.b){var c=this.b,d=function(b){return a.getUniformLocation(c,b)};this.I=d("a");this.H=d("b");this.A=d("c");this.L=d("d");this.K=d("e");this.m=d("f");this.l=d("g");this.J=d("h");this.f=d("j");this.g=d("k");this.h=d("l");this.i=d("m");this.j=d("n");this.C=d("o");this.v=d("p");this.o=d("q");this.la=d("v");this.c=d("w");this.B=d("D");this.s=d("E");this.D=d("F");this.G=d("G");this.u=this.b}a.useProgram(this.u);this.I&&a.uniform4fv(this.I,b.s.value); +this.H&&a.uniform4fv(this.H,b.o.value);this.A&&a.uniform1f(this.A,b.b.value);this.L&&a.uniform4fv(this.L,b.B.value);this.K&&a.uniform1i(this.K,b.A.value);this.m&&a.uniform4fv(this.m,b.v.value);this.l&&a.uniform1i(this.l,b.u.value);this.J&&a.uniform1f(this.J,b.c.value);this.f&&a.uniform4fv(this.f,b.C.value);this.g&&a.uniform3fv(this.g,b.g.value);this.h&&a.uniform3fv(this.h,b.h.value);this.i&&a.uniformMatrix4fv(this.i,!1,b.i.value);this.j&&a.uniform1f(this.j,b.j.value);this.C&&a.uniform1f(this.C,b.m.value); +this.v&&a.uniformMatrix4fv(this.v,!1,b.a.value);this.o&&a.uniform1i(this.o,b.l.value);this.la&&a.uniform1f(this.la,b.la.value);this.c&&a.uniform1f(this.c,b.qb.value);this.B&&a.uniform1f(this.B,b.H.value);this.s&&a.uniform1f(this.s,b.J.value);this.D&&a.uniform1i(this.D,b.Ia.value);this.G&&a.uniform4fv(this.G,b.Ja.value)};function kX(a,b,c,d){this.f=a;this.i=b;this.h=yV(a,iX);this.g=d;this.c=new EV(6,[[4,5123],[4,5123],[2,5126],[4,5122]]);this.j=new ir(a,this.c.a,this.c.b,65536);this.a=c} +function lX(a,b,c,d){for(var e=a.f,f=a.i,g=a.c,h=a.h,k=!1,l=0;l<b.length;++l){var m=b[l];if(m.b&&m.b.a.W[d]){k=!0;break}if(m.a.W[d]){k=!0;break}}if(k){TV(e,c,3,3,1,2,1);fr(a.a,4);f.Ia.set(4);f.Ja.set(a.a.c,a.a.a,1/a.a.c,1/a.a.a);FV(e,g);f.H.set(c.C);f.J.set(143);k=hq(e);h.bind(k,f);for(l=0;l<b.length;++l){m=b[l];if(m.b){f=m.b.a.W[d];var n=m.a.W[d]}else f=m.a.W[d],n=null;if(f||n)m=m.a,k.uniform4f(h.f,m.g,m.h,m.m,m.b),k.uniform1f(h.la,m.la),k.uniform1f(h.c,c.l/m.la),NV(e,g,f,n)}iq(e);GV(e,g);gr(a.a)}} +kX.prototype.b=function(a,b){a=a.a;var c=a.c,d=this.c.f,e=b.a;if(!e.length)return 2;for(var f=new Uint32Array(e.length*this.c.h),g=new Float32Array(f.buffer),h=0,k=0;k<e.length;++k){var l=e[k],m=l,n=m.label.b,p=pI(n.a,a.b,a.g),q=pI(n.b,a.b,a.h);n=pI(n.altitude,a.b,0);l=ZV(c,l.a);l=oI(l.x,l.y);var t=m.c;if(t){var v=m.oa*a.la,u=m.b*a.la,w=t.a,y=t.b,A=Math.round(t.width*a.la),z=Math.round(t.height*a.la);t.c||(A=z=0);var C=A+2,I=-2-z/2,S=z/2+2;z=w+-2;t=y+I;w+=C;y+=S;A=16*(v+-2);I=16*(u+I);v=16*(v+C); +u=16*(u+S);C=this.g&&m.label.i?1:0;m=tW(m,!!C);f[h+0]=p;f[h+1]=q;f[h+2]=n;f[h+3]=l;g[h+4]=m;g[h+5]=C;f[h+6]=oI(A,u);f[h+7]=oI(z,y);h+=d;f[h+0]=p;f[h+1]=q;f[h+2]=n;f[h+3]=l;g[h+4]=m;g[h+5]=C;f[h+6]=oI(A,I);f[h+7]=oI(z,t);h+=d;f[h+0]=p;f[h+1]=q;f[h+2]=n;f[h+3]=l;g[h+4]=m;g[h+5]=C;f[h+6]=oI(v,I);f[h+7]=oI(w,t);h+=d;f[h+0]=p;f[h+1]=q;f[h+2]=n;f[h+3]=l;g[h+4]=m;g[h+5]=C;f[h+6]=oI(A,u);f[h+7]=oI(z,y);h+=d;f[h+0]=p;f[h+1]=q;f[h+2]=n;f[h+3]=l;g[h+4]=m;g[h+5]=C;f[h+6]=oI(v,I);f[h+7]=oI(w,t);h+=d;f[h+0]=p; +f[h+1]=q;f[h+2]=n;f[h+3]=l;g[h+4]=m;g[h+5]=C;f[h+6]=oI(v,u);f[h+7]=oI(w,y);h+=d}}h&&(c=PV(this.j,f),jO(a.a,c),a.W[b.b]=c.a[0]);return 2};function mX(){this.m=this.b=this.Ya=this.i=this.j=this.C=this.D=this.l=this.o=this.u=this.h=this.g=this.f=this.c=this.G=this.B=this.s=this.v=this.A=null;this.H={}}var nX="#define _b 8\n#define _c 8000\n#define _d "+QB+"\n#define _e 2\n#define _f 16\n#define _g 8\n#define _h 22\n#define _i vec4(0., 0., 0., 0.2)\n#define _j 2\n#define _k 9\n#define _l 6\n#define _m 3\n#define _n 0\n#define _o 1\n#define _p 2\n#define _q 4\n#define _r 5\n#define _s 12\n#define _t 0\n#define _u 8\n#define _v 2\n#define _w 1\n\n"; +mX.prototype.a=function(a,b){b="#define _a "+b.f+"\n";var c=this.H[b];c||(c=zV(a,nX+b+"precision highp float;\n#if _a==1\nvarying vec3 e;\n#endif\n#if _a==1\nuniform mat4 l;\n#else\n#endif\nuniform vec4 n;uniform sampler2D o;vec2 J(vec2 t,float v){float w=float(_s);t.y=w*t.y+v;return (t+.5)*n.zw;}precision highp float;varying vec3 r;attribute vec3 s;uniform vec2 t;void main(){vec3 v=mat3(l)*s;e=normalize(v);vec4 w=l*vec4(s,1);w/=w.w;gl_Position=w;vec2 x=J(t,float(_m));r=texture2D(o,x).rgb;}",nX+b+ +"precision highp float;\n#if _a==1\nuniform float d;varying vec3 e;\n#endif\nfloat w(){\n#if _a==1\nfloat u,v;u=dot(e,vec3(-1.,1,-1.));v=clamp((u-.5)/4.+1.,.5,1.);return mix(1.,v,d);\n#else\nreturn 1.;\n#endif\n}precision highp float;precision highp float;varying vec3 r;void main(){float u=w();gl_FragColor=vec4(r*u,1);}",["s"]),this.H[b]=c);this.b=c}; +mX.prototype.bind=function(a,b){this.a(a,b);if(this.m!=this.b){var c=this.b,d=function(b){return a.getUniformLocation(c,b)};this.A=d("a");this.v=d("b");this.s=d("c");this.B=d("d");this.G=d("f");this.c=d("g");this.f=d("h");this.g=d("i");this.h=d("j");this.u=d("k");this.o=d("l");this.l=d("m");this.D=d("n");this.C=d("o");this.j=d("p");this.i=d("q");this.Ya=d("t");this.m=this.b}a.useProgram(this.m);this.A&&a.uniform4fv(this.A,b.s.value);this.v&&a.uniform4fv(this.v,b.o.value);this.s&&a.uniform1f(this.s, +b.b.value);this.B&&a.uniform1f(this.B,b.c.value);this.G&&a.uniform4fv(this.G,b.C.value);this.c&&a.uniform3fv(this.c,b.g.value);this.f&&a.uniform3fv(this.f,b.h.value);this.g&&a.uniformMatrix4fv(this.g,!1,b.i.value);this.h&&a.uniform1f(this.h,b.j.value);this.u&&a.uniform1f(this.u,b.m.value);this.o&&a.uniformMatrix4fv(this.o,!1,b.a.value);this.l&&a.uniform1i(this.l,b.l.value);this.D&&a.uniform4fv(this.D,b.B.value);this.C&&a.uniform1i(this.C,b.A.value);this.j&&a.uniform4fv(this.j,b.v.value);this.i&&a.uniform1i(this.i, +b.u.value);this.Ya&&a.uniform2fv(this.Ya,b.Ya.value)};function oX(){this.a=1;this.f=Array(8192);this.b=Array(8192);this.c=0}function pX(a,b){return a.f[b]!=a.a?(a.f[b]=a.a,(b=!a.b[b])&&a.c++,b):!1}function qX(a,b){return a.f[b]==a.a}function rX(a,b,c){a.b[b]&&!c&&qX(a,b)&&a.c++;a.b[b]=c};function sX(a,b){this.i=a;this.f=null;this.j=this.l=0;this.g=this.c=!1;a=this.b=b;a.f=this.A;a.h=this||null;a=D(this.B,this);this.b.i=a;this.a=new oX;this.m=null;this.h=0;this.v=new Uint8Array(48);this.u=new Uint8Array(48);this.s=new Uint8Array(48);this.o=0} +function tX(a,b){var c=a.i;a.f||(a.f=c.createTexture(),c.activeTexture(33984+c.a.vb()),c.bindTexture(3553,a.f),c.texParameteri(3553,10240,9728),c.texParameteri(3553,10241,9728),c.texParameteri(3553,10242,33071),c.texParameteri(3553,10243,33071),a.l=0,a.j=0,a.c=!1);a.c||(c.activeTexture(33984+c.a.vb()),uX(a),c.a.xa(33984+c.a.vb()-33984,null),a.c=!0);b[0]=a.l;b[1]=a.j;return a.f}function vX(a,b,c,d){var e=a%d;a=Math.floor(a/d);b[c+1]=e&255;b[c+2]=e>>8&255;b[c+3]=a} +function wX(a,b,c){c.x=b%a.i;c.y=Math.floor(b/a.i)}function xX(a,b){for(var c=!1,d=0;d<b.length;++d)c|=pX(a.a,b[d]);c&&(a.c=!1)} +function uX(a){var b=a.i,c=a.f;b.activeTexture(33984+b.a.vb());b.bindTexture(3553,c);var d=a.i.i;var e=a.b;c=QA(e.a)+1;ZB(e)&&(e=QA(e.b)+1,c=c>e?c:e);var f=Math.max(Math.ceil(c/d),1);e=Math.min(512*Math.ceil(c/512),d);var g=!1;e!=a.l&&(g=!0);d=Math.min(12*f,d);d!=a.j&&(g=!0);g&&(a.l=e,a.j=d,Uo(jq(b,3553),null,e,d,6408,5121,0));d=g||a.g;a.g=!1;g=1;ZB(a.b)&&(g=a.b,ZB(g)?(g=1-(g.j-E())/167,g=XB(g)):g=1);for(var h=f=0;h<c;++h)if(qX(a.a,h)){if(d||!a.a.b[h]){if(1!=g){var k=RA(a.b.b,h);pA(RA(a.b.a,h),a.h, +a.u);pA(k,a.h,a.v);var l=a.v,m=a.u,n=a.s;k=g;for(var p=0;12>p;p++)n[p]=m[p];l=l.subarray(12);m=m.subarray(12);n=n.subarray(12);rA(l,m,n,k,k)}else pA(RA(a.b.a,h),a.h,a.s);k=h%e;n=12*Math.floor(h/e);m=a.s;Vo(jq(b,3553),m,k,n,1,12,6408,5121,0);rX(a.a,h,!0);f++}}else d&&rX(a.a,h,!1)}sX.prototype.A=function(a,b){for(var c=!1,d=0;d<a.length;++d){var e=a[d];rX(this.a,e,!1);!c&&qX(this.a,e)&&(c=!0);e=b[d];var f=!0;e&&!($z(e)?0:e.l||e.s||e.j||e.C)&&(f=!1)}c&&(f||this.o++,yX(this))}; +sX.prototype.B=function(){this.g=!0;yX(this)};function yX(a){a.c&&(a.c=!1,a.m&&a.m())};function zX(a){this.b=yV(a,mX);this.c=new EV(1,[[3,5126]]);var b=[],c=Math.sin(83/90*Math.PI/2),d=Math.cos(83/90*Math.PI/2);b.push(0,0,6371010);for(var e=0;10>=e;e++)b.push(6371010*d*Math.sin(e/10*2*Math.PI),6371010*d*Math.cos(e/10*2*Math.PI),6371010*c);b.push(0,0,-6371010);for(e=10;0<=e;e--)b.push(6371010*d*Math.sin(e/10*2*Math.PI),6371010*d*Math.cos(e/10*2*Math.PI),6371010*-c);this.f=HV(a,b);this.a=b.length/3}var AX=new eo;function BX(){this.o=this.b=this.m=this.s=this.v=this.i=this.h=this.g=this.f=this.c=this.C=this.j=this.l=this.D=this.G=this.u=this.A=this.B=null;this.H={}}var CX="#define _b 8\n#define _c 8000\n#define _d "+QB+"\n#define _e 2\n#define _f 16\n#define _g 8\n#define _h vec4(0., 0., 0., 0.2)\n#define _i 2\n#define _j 9\n#define _k 6\n#define _l 3\n#define _m 0\n#define _n 1\n#define _o 2\n#define _p 4\n#define _q 5\n#define _r 12\n#define _s 0\n#define _t 8\n#define _u 2\n#define _v 1\n#define _w 22\n\n"; +BX.prototype.a=function(a,b){b="#define _a "+b.f+"\n";var c=this.H[b];c||(c=zV(a,CX+b+"precision highp float;uniform float c,o;uniform vec4 d,f,j;uniform sampler2D e,g;vec2 xa(vec2 C,float D){float E=float(_r);C.y=E*C.y+D;return (C+.5)*d.zw;}vec2 Aa(vec4 C){return vec2(C.g+C.b*256.,C.a);}vec2 Ba(vec2 C){vec4 D=texture2D(g,(floor(C*65535.+.5)+.5)*f.zw);D=floor(D*255.+.5);return Aa(D);}float Ca(vec2 C,vec2 D){vec4 E=texture2D(e,C+D);float F,G;F=E.r*255.*4.;G=E.g*(255./64.);return F+G;}\n#if _a==1\nuniform float h;varying vec3 i;\n#endif\nuniform vec3 k,l;uniform mat4 m;\n#if _a==1\nuniform mat4 p;vec3 Da(vec3 C){const float D=6371010.;float E,F,G,H,I,J,K,L,M,N;E=C.x;F=exp(C.y);G=F*F;H=2.*F/(1.+G);I=(G-1.)/(1.+G);J=C.z*D*H;K=J+D;L=K*H*cos(E);M=K*H*sin(E);N=K*I;return vec3(L,M,N);}vec4 Ea(vec3 C){vec4 D,G;D=m*vec4(C,1);vec3 E,F;E=C;E/=o;E+=k+l;E.xy-=.5;E.y=-E.y;E*=3.141592653589793*2.;F=Da(E);G=p*vec4(F,1);G/=G.w;D/=D.w;return mix(D,G,h);}\n#else\nvec4 Ea(vec3 C){return m*vec4(C,1);}\n#endif\nvec3 Fa(vec3 C,vec3 D){vec3 E=C-k+(D-l);return E*o;}vec3 Ga(vec3 C){vec3 D,E;D=vec3(j.x,j.y,0);E=C*j.w;E.xy*=1./float(_f);return Fa(D,E);}float Ha(float C){float D,E;D=1./float(_w+1);E=1.-D-j.z*D;return C*D+E;}varying vec4 r,t;varying vec3 s;const float B=1.;attribute vec4 u;attribute vec4 v;attribute vec4 w;attribute float x;void main(){bool C,D,F,G,H,I,J,K,L,M,N,la,qa;C=true;if(x==2.)C=false;if(x==4.)C=false;if(x==5.)C=false;D=true;if(x==1.)D=false;if(x==2.)D=false;if(x==5.)D=false;float E,S,T,U,V,W,X,Y,aa,ba,ca,fa,ia,ja,ka,ma,na,oa,pa,ta,ua,va,wa;E=floor(w.w*255.+.5);F=fract(E*(1./2.))>=.5;G=fract(E*(1./4.))>=.5;H=fract(E*(1./8.))>=.5;I=fract(E*(1./16.))>=.5;J=fract(E*(1./32.))>=.5;K=fract(E*(1./64.))>=.5;L=fract(E*(1./128.))>=.5;M=F?I:G;N=F?J:H;vec2 O,P,Q,R,da,ea;O=Ba(v.xy);P=vec2(0,1.*d.w);Q=xa(O,float(_k));R=xa(O,float(_j));S=float(_s);r=texture2D(e,(F?R:Q)+S*P);T=float(_v);U=Ca(Q,T*P);V=Ca(R,T*P);W=F?V:U;X=W*.5;Y=U*.5;const float Z=3.141592653589793*2./256.;aa=floor(w.x*255.+.5);ba=floor((C?w.y:w.z)*255.+.5)*.5;ca=aa+ba;aa*=Z;ba*=Z;ca*=Z;da=vec2(cos(aa),sin(aa));ea=vec2(sin(ca),-cos(ca))/cos(ba);fa=tan(ba);vec3 ga,ha,ra;ga=Ga(vec3(floor(u.xy*32767.+.5),0));ha=Ga(vec3(floor(u.zw*32767.+.5),0));ia=length(ha.xy-ga.xy);if(N&&L)ia-=Y;if(M&&K)ia-=Y;ja=B/c;ka=ja*.5;la=C?M:N;ma=la?X+ka:0.;na=X+ka;oa=C?-1.:1.;pa=D?-1.:1.;s.x=C?0.:ia;s.y=0.;s.x+=ma*oa;s.x+=na*pa*fa;s.y+=na*pa;s.xy/=ia;s.z=float(M);s.z+=float(N)*.5;t.x=-ia/ja;t.y=-.5*W/ja+.5;qa=C?K:L;if(la&&qa)ma-=Y;ra=C?ga:ha;ra.xy+=ma*oa*da;ra.xy+=na*pa*ea;vec4 sa=Ea(ra);ta=v.z;ua=v.w;va=F?ua:ta;wa=Ha(va);gl_Position=vec4(sa.xy/sa.w,wa,1);if(sa.w<0.||r.a==0.)gl_Position=vec4(0);}", +CX+b+"precision highp float;precision highp float;\n#if _a==1\nvarying vec3 i;\n#endif\nvarying vec4 r,t;varying vec3 s;const float A=1.;float K(float B){const float C=0.;const float D=1.;const float E=.3;const float F=.3;const float G=2.*C-2.*D+E+F;const float H=3.*D-3.*C-2.*E-F;const float I=E;const float J=C;return clamp(((G*B+H)*B+I)*B+J,0.,1.);}void main(){vec2 B=vec2(s.x-clamp(s.x,0.,1.),s.y);float C,D,E,F,G,H,I;C=B.x*B.x+B.y*B.y;D=t.x;E=t.y;F=sqrt(C)*D;G=clamp(F-E+1.,0.,1.);H=clamp(F+E,0.,1.);if(A>1.){G=K(G);H=K(H);}I=clamp(G-H,0.,1.);if(I==0.)discard;gl_FragColor=r;gl_FragColor.a*=I;}", +["u","v","w","x"]),this.H[b]=c);this.b=c}; +BX.prototype.bind=function(a,b){this.a(a,b);if(this.o!=this.b){var c=this.b,d=function(b){return a.getUniformLocation(c,b)};this.B=d("a");this.A=d("b");this.u=d("c");this.G=d("d");this.D=d("e");this.l=d("f");this.j=d("g");this.C=d("h");this.c=d("j");this.f=d("k");this.g=d("l");this.h=d("m");this.i=d("n");this.v=d("o");this.s=d("p");this.m=d("q");this.o=this.b}a.useProgram(this.o);this.B&&a.uniform4fv(this.B,b.s.value);this.A&&a.uniform4fv(this.A,b.o.value);this.u&&a.uniform1f(this.u,b.b.value);this.G&& +a.uniform4fv(this.G,b.B.value);this.D&&a.uniform1i(this.D,b.A.value);this.l&&a.uniform4fv(this.l,b.v.value);this.j&&a.uniform1i(this.j,b.u.value);this.C&&a.uniform1f(this.C,b.c.value);this.c&&a.uniform4fv(this.c,b.C.value);this.f&&a.uniform3fv(this.f,b.g.value);this.g&&a.uniform3fv(this.g,b.h.value);this.h&&a.uniformMatrix4fv(this.h,!1,b.i.value);this.i&&a.uniform1f(this.i,b.j.value);this.v&&a.uniform1f(this.v,b.m.value);this.s&&a.uniformMatrix4fv(this.s,!1,b.a.value);this.m&&a.uniform1i(this.m,b.l.value)};function DX(a,b){this.c=a;this.g=b;this.f=yV(a,BX);this.a=new EW(!1);this.h=new ir(a,this.a.f.a,this.a.f.b,void 0);this.i=HV(a,[0,2,1,3,4,5])}function EX(a,b,c,d,e,f){this.za=a;this.yf=b;this.Ef=c;this.mf=d;this.Hb=e;this.Ie=f} +DX.prototype.b=function(a,b){var c=a.a,d=a.data,e=d.a;b=rI(d.getZoom(),b);if(!e||16<d.c||c.I||!(Ey(e)&&jy(Fy(e))||Gy(e)&&ly(Hy(e))))return 2;var f=d.b,g=c.f,h=d.getZoom();a=a.a.c;var k=[];if(Ey(e)&&jy(Fy(e)))for(var l=Fy(e).a,m=l.length,n=f.a[1],p=0;p<m;p++){var q=n[p],t=q.ka();t=CK(g,t);Xz(t,h)&&(k.push(new EX(q.za,q,l[p],null,1,k.length)),k.push(new EX(q.b,q,l[p],null,0,k.length)))}if(Gy(e)&&ly(Hy(e)))for(e=Hy(e).a,l=e.length,m=f.a[2],p=0;p<l;p++)f=e[p],n=m[p],t=n.ka(),t=CK(g,t),d.getZoom(),Xz(t, +h)&&!(1>t.c)&&null!=f.a&&(null==f.f?0:f.f)&&(k.push(new EX(n.za+1,n,null,f,0,k.length)),k.push(new EX(n.za+2,n,null,f,1,k.length)));k.sort(function(a,b){return a.za-b.za||a.Ie-b.Ie});this.a.reset(0,0,1,d.c);for(p=0;p<k.length;p++)g=k[p],h=g.yf,e=g.Ef,f=g.mf,t=h.ka(),t=ZV(a,t),e?FX(this,e,h,g.Hb,t,b,d.getZoom()):f&&GX(this,f,h,g.Hb,t);0!=this.a.a&&(d=PV(this.h,this.a.b,this.a.a),jO(c.a,d),c.I=d.a[0]);return 2}; +function FX(a,b,c,d,e,f,g){a=a.a;FW(a,Vw(b),Ww(b));a.D=d;GW(a,e);a.o=65535-c.b|65535-c.za<<16;FI(b,a,g,f)}function GX(a,b,c,d,e){a=a.a;FW(a,1,1);a.D=d;GW(a,e);a.o=65535-(c.za+1)|65535-(c.za+2)<<16;II(ux(b),a)};function HX(){this.f=this.b=this.g=this.c=null;this.h={}}HX.prototype.a=function(a){var b=this.h["\n"];b||(b=zV(a,"\n\nprecision highp float;attribute vec2 a;void main(){gl_Position=vec4(a,0,1);}","\n\nprecision highp float;uniform float b,c;void main(){float d,f;d=gl_FragCoord.y/c;if(d<b-40.)discard;vec4 e=d<b?vec4(.9,.9,.9,0):vec4(.7,.8,1,1);f=smoothstep(0.,40.,abs(d-b));gl_FragColor=mix(vec4(.95,.95,.95,1),e,f);}",["a"]),this.h["\n"]=b);this.b=b}; +HX.prototype.bind=function(a,b){this.a(a,b);if(this.f!=this.b){var c=this.b;this.c=a.getUniformLocation(c,"b");this.g=a.getUniformLocation(c,"c");this.f=this.b}a.useProgram(this.f);this.c&&a.uniform1f(this.c,b.P.value);this.g&&a.uniform1f(this.g,b.b.value)};function IX(a){this.c=yV(a,HX);this.a=new EV(1,[[2,5126]]);this.b=HV(a,[-1,-1,-1,1,1,-1,1,1])}function JX(a,b,c,d,e){d.P.set(e);TV(b,c,3,1,1,2,1);FV(b,a.a);KV(b,a.b,a.a);c=hq(b);a.c.bind(c,d);b.drawArrays(5,0,4);iq(b);GV(b,a.a)};function KX(){this.h=this.b=this.f=this.g=this.j=this.l=this.i=this.c=null;this.m={}} +KX.prototype.a=function(a){var b=this.m["\n"];b||(b=zV(a,"\n\nprecision highp float;varying vec2 a;attribute vec2 b;uniform float c;void main(){a=b;a.x*=c;gl_Position=vec4(b,1,1);}","\n\nprecision highp float;varying vec2 a;uniform float d;uniform vec3 e,f,g;uniform vec2 h;void main(){float i,j;i=d;j=length(a-h)/i;if(j<1.)discard;else{j=clamp(pow(j-1.,.5),0.,1.5);vec3 k=mix(mix(g,f,j),e,j-.5);gl_FragColor=vec4(k,1);}}",["b"]),this.m["\n"]=b);this.b=b}; +KX.prototype.bind=function(a,b){this.a(a,b);if(this.h!=this.b){var c=this.b;this.c=a.getUniformLocation(c,"c");this.i=a.getUniformLocation(c,"d");this.l=a.getUniformLocation(c,"e");this.j=a.getUniformLocation(c,"f");this.g=a.getUniformLocation(c,"g");this.f=a.getUniformLocation(c,"h");this.h=this.b}a.useProgram(this.h);this.c&&a.uniform1f(this.c,b.O.value);this.i&&a.uniform1f(this.i,b.Ka.value);this.l&&a.uniform3fv(this.l,b.Pa.value);this.j&&a.uniform3fv(this.j,b.Oa.value);this.g&&a.uniform3fv(this.g, +b.Ca.value);this.f&&a.uniform2fv(this.f,b.ya.value)};function LX(a,b){this.c=yV(a,KX);this.a=new EV(1,[[2,5126]]);this.b=HV(a,[-1,-1,-1,1,1,-1,1,1]);b.Pa.set(.09,.1,.28);b.Oa.set(.53,.81,.98);b.Ca.set(.7,.78,.86)};function MX(a,b){this.h=a;this.j=b;this.i=yV(a,lW);this.a=new EV(1,[[2,5126]]);this.f=0;this.g=a.createTexture();Uo(this.g,new Uint8Array([255,255,255,255]),1,1,6408,5121,0);this.b=null;this.c=0};function NX(){this.o=this.b=this.v=this.m=this.s=this.A=this.i=this.h=this.g=this.f=this.c=this.D=this.j=this.l=this.G=this.H=this.u=this.B=this.C=null;this.I={}}var OX="#define _b 8\n#define _c 8000\n#define _d "+QB+"\n#define _e 2\n#define _f 16\n#define _g 8\n#define _h vec4(0., 0., 0., 0.2)\n#define _i 2\n#define _j 9\n#define _k 6\n#define _l 3\n#define _m 0\n#define _n 1\n#define _o 2\n#define _p 4\n#define _q 5\n#define _r 12\n#define _s 0\n#define _t 8\n#define _u 2\n#define _v 1\n#define _w 22\n\n"; +NX.prototype.a=function(a,b){b="#define _a "+b.f+"\n";var c=this.I[b];c||(c=zV(a,OX+b+"precision highp float;uniform vec4 b,d,f;uniform float c,o,F;vec2 da(vec2 H){return (H*b.xy+b.xy)*.5;}vec2 ea(vec2 H){return (H*b.zw-vec2(.5))*2.;}vec2 fa(vec4 H,vec2 I,vec2 J,float F){I*=vec2(1,-1.);J*=vec2(1,-1.);vec2 K,L,M;K=da(H.xy/H.w);L=K+I;M=floor(L+.5);M+=(1.-F)*(L-M);M+=J;return M;}vec2 ga(vec4 H,vec2 I){return ea(I)*H.w;}uniform sampler2D e,g;vec2 ha(vec2 H,float I){float J=float(_r);H.y=J*H.y+I;return (H+.5)*d.zw;}vec2 ia(vec4 H){return vec2(H.g+H.b*256.,H.a);}float ja(float H){return mod(H,32.)/31.;}void ka(vec2 H,out float I,out vec2 J){vec4 K=texture2D(g,(floor(H*65535.+.5)+.5)*f.zw);K=floor(K*255.+.5);I=ja(K.r);J=ia(K);}\n#if _a==1\nuniform float h;varying vec3 i;\n#endif\nuniform vec3 k,l;uniform mat4 m;\n#if _a==1\nuniform mat4 p;vec3 la(vec3 H){const float I=6371010.;float J,K,L,M,N,O,P,Q,R,S;J=H.x;K=exp(H.y);L=K*K;M=2.*K/(1.+L);N=(L-1.)/(1.+L);O=H.z*I*M;P=O+I;Q=P*M*cos(J);R=P*M*sin(J);S=P*N;return vec3(Q,R,S);}vec4 ma(vec3 H){vec4 I,L;I=m*vec4(H,1);vec3 J,K;J=H;J/=o;J+=k+l;J.xy-=.5;J.y=-J.y;J*=3.141592653589793*2.;K=la(J);L=p*vec4(K,1);L/=L.w;I/=I.w;return mix(I,L,h);}\n#else\nvec4 ma(vec3 H){return m*vec4(H,1);}\n#endif\nvec3 na(vec3 H,vec3 I){vec3 J=H-k+(I-l);return J*o;}vec3 oa(vec2 H,vec2 I,vec2 J){vec3 K,L;K=vec3(H.x,I.x,J.x)*65535.+.5;\n#if _a==1\nK-=fract(K);\n#else\nK=floor(K);\n#endif\nK=K/65536.;K=(fract(K+.5)-.5)*4.;L=vec3(H.y,I.y,J.y)*65535.;L/=1073741824.;return na(K,L);}vec4 pa(vec2 H,vec2 I,vec2 J){vec3 K=oa(H,I,J);return ma(K);}varying float r;varying vec4 s,t,u,w;varying vec2 v;attribute float x;attribute vec4 A;attribute vec4 B;attribute vec4 C;attribute vec2 D;attribute vec2 E;void main(){float H,J,L,N,T,U,V,W,X,aa;H=floor(x*255.+.5);vec2 I,K,M,O,P,Q,R,S,Y,Z,ca;I=vec2(floor(H/2.),mod(floor((H+1.)/2.),2.));ka(C.zw,J,K);L=float(_m);M=ha(K,L);s=texture2D(e,M);N=float(_n);O=ha(K,N);t=texture2D(e,O);r=J;gl_Position=pa(B.yx,B.wz,C.yx);gl_Position/=gl_Position.w;gl_Position.z=D.x;P=c*floor(E*32767.+.5)/float(_f);Q=floor(A.xy*65535.+.5)*c;R=fa(gl_Position,P+vec2(0,Q.y/2.),vec2(0),F);S=fa(gl_Position,P+vec2(Q.x-1.,1.-Q.y/2.),vec2(0),F);T=c*floor(floor(A.w*65535.+.5)/16.);u=vec4(R,S);v=vec2(c*D.y,T);U=c*mod(floor(A.w*65535.+.5),16.);V=floor(A.z*65535.+.5);W=1.-floor(abs(1.5-V));X=2.*mod(V,2.)-1.;Y=X*vec2(W-1.,W);Z=fa(gl_Position,vec2(0),vec2(0),F);Z+=((S+R)*.5-Z)*abs(Y)+Y*((S-R)*.5+vec2(U));aa=sign(U);w=mix(vec4(u.xy,0,0),vec4(Z,U+1.,V),aa);vec4 ba=u;ba.x=min(w.x,ba.x)-1.;ba.y=min(w.y,ba.y)-T-1.;ba.z=max(w.x,ba.z)+T+1.;ba.w=max(w.y,ba.w)+1.;ca=mix(ba.xy,ba.zw,I);gl_Position.xy=ga(gl_Position,ca);gl_Position.xy*=sign(J);}", +OX+b+"precision highp float;precision highp float;\n#if _a==1\nvarying vec3 i;\n#endif\nprecision highp float;varying float r;varying vec4 s,t,u,w;varying vec2 v;float S(vec2 G,vec4 H){vec2 I=max(H.xy-G,G-1.-H.zw);float J=max(I.x,I.y);return clamp(.5-J,0.,1.);}float T(vec2 G,float H){vec2 I=G-w.xy;float J,K,L;J=floor(w.w+.5);I=mix(I,-I.yx,sign(mod(J,3.)));I*=2.*mod(J,2.)-1.;I.x-=H*1.414;K=clamp(I.x-abs(I.y),0.,1.);L=clamp(w.z+.5-I.x,0.,1.);return K*L;}float U(vec2 G){return max(S(G,u),T(G,0.));}void main(){vec2 G=gl_FragCoord.xy;float H,I,K,L,M,N,O;H=U(G);I=v.x;vec4 J,P,Q,R;J=u+vec2(I,-I).xxyy;K=S(G,J);L=T(G,I);M=max(K,L);N=0.;O=v.y;if(O>0.){vec2 P=G+vec2(-O,O);N+=U(P);N+=U(P+vec2(1,0));N+=U(P+vec2(0,-1.));N+=U(P+vec2(1,-1.));N*=s.a*.25;}P=mix(t,s,M);P.a*=H;Q=_h*vec4(1,1,1,N);R.rgb=P.rgb*P.a+Q.rgb*Q.a*(1.-P.a);R.a=1.-(1.-P.a)*(1.-Q.a);if(R.a==0.)discard;R.rgb/=R.a;R.a*=r;gl_FragColor=R;}", +"xABCDE".split("")),this.I[b]=c);this.b=c}; +NX.prototype.bind=function(a,b){this.a(a,b);if(this.o!=this.b){var c=this.b,d=function(b){return a.getUniformLocation(c,b)};this.C=d("a");this.B=d("b");this.u=d("c");this.H=d("d");this.G=d("e");this.l=d("f");this.j=d("g");this.D=d("h");this.c=d("j");this.f=d("k");this.g=d("l");this.h=d("m");this.i=d("n");this.A=d("o");this.s=d("p");this.m=d("q");this.v=d("F");this.o=this.b}a.useProgram(this.o);this.C&&a.uniform4fv(this.C,b.s.value);this.B&&a.uniform4fv(this.B,b.o.value);this.u&&a.uniform1f(this.u, +b.b.value);this.H&&a.uniform4fv(this.H,b.B.value);this.G&&a.uniform1i(this.G,b.A.value);this.l&&a.uniform4fv(this.l,b.v.value);this.j&&a.uniform1i(this.j,b.u.value);this.D&&a.uniform1f(this.D,b.c.value);this.c&&a.uniform4fv(this.c,b.C.value);this.f&&a.uniform3fv(this.f,b.g.value);this.g&&a.uniform3fv(this.g,b.h.value);this.h&&a.uniformMatrix4fv(this.h,!1,b.i.value);this.i&&a.uniform1f(this.i,b.j.value);this.A&&a.uniform1f(this.A,b.m.value);this.s&&a.uniformMatrix4fv(this.s,!1,b.a.value);this.m&&a.uniform1i(this.m, +b.l.value);this.v&&a.uniform1f(this.v,b.H.value)};function PX(a,b){this.c=a;this.g=b;this.f=yV(a,NX);this.a=new EV(6,[[4,5121],[4,5123],[4,5123],[4,5123],[2,5126],[2,5122]]);this.h=new ir(a,this.a.a,this.a.b,65536)} +function QX(a,b,c,d){var e=a.c,f=a.g,g=a.a;a=a.f;for(var h=!1,k=0;k<b.length;++k){var l=b[k];if(l.b&&l.b.a.ha[d]){h=!0;break}if(l.a.ha[d]){h=!0;break}}if(h){TV(e,c,3,3,1,2,1);FV(e,g);f.H.set(c.C);c=hq(e);a.bind(c,f);for(k=0;k<b.length;++k)if(b[k].b?(f=b[k].b.a.ha[d],h=b[k].a.ha[d]):(f=b[k].a.ha[d],h=null),f||h)l=b[k].a,c.uniform4f(a.c,l.g,l.h,l.m,l.b),NV(e,g,f,h);iq(e);GV(e,g)}} +PX.prototype.b=function(a,b){a=a.a;var c=a.c,d=this.a.f,e=b.a;if(!e.length)return 2;for(var f=new Uint32Array(e.length*this.a.h),g=new Float32Array(f.buffer),h=0,k=[0,1,2,0,2,3],l=0;l<e.length;++l)for(var m=e[l],n=m,p=m.label.b,q=ZV(c,m.a),t=0;t<k.length;t++)f[h+0]=k[t],f[h+1]=oI(n.width,n.height),f[h+2]=oI(n.h,n.i<<4|n.g&15),f[h+3]=pI(p.a,a.b,a.g),f[h+4]=pI(p.b,a.b,a.h),f[h+5]=pI(p.altitude,a.b,0),f[h+6]=oI(q.x,q.y),g[h+7]=tW(m),g[h+8]=n.m,f[h+9]=oI(16*n.oa,16*n.b),h+=d;c=PV(this.h,f);jO(a.a,c); +a.ha[b.b]=c.a[0];return 2};function RX(){this.o=this.b=this.c=this.f=this.h=this.g=this.l=this.m=this.i=this.j=null;this.s={}} +RX.prototype.a=function(a){var b=this.s["\n"];b||(b=zV(a,"\n\nprecision highp float;varying vec2 a;uniform vec2 b,d,e;uniform float c,f;attribute vec2 g;void main(){vec2 h,i;h=g*b*c+e;i=2.*(h/d)-1.;i.y*=f;gl_Position=vec4(i,1,1);a=g;}","\n\nprecision highp float;varying vec2 a;uniform sampler2D h;uniform float i,j;void main(){gl_FragColor=texture2D(h,a);gl_FragColor.a=gl_FragColor.a*i+j;}",["g"]),this.s["\n"]=b);this.b=b}; +RX.prototype.bind=function(a,b){this.a(a,b);if(this.o!=this.b){var c=this.b,d=function(b){return a.getUniformLocation(c,b)};this.j=d("b");this.i=d("c");this.m=d("d");this.l=d("e");this.g=d("f");this.h=d("h");this.f=d("i");this.c=d("j");this.o=this.b}a.useProgram(this.o);this.j&&a.uniform2fv(this.j,b.Y.value);this.i&&a.uniform1f(this.i,b.W.value);this.m&&a.uniform2fv(this.m,b.ha.value);this.l&&a.uniform2fv(this.l,b.Z.value);this.g&&a.uniform1f(this.g,b.U.value);this.h&&a.uniform1i(this.h,b.V.value); +this.f&&a.uniform1f(this.f,b.T.value);this.c&&a.uniform1f(this.c,b.S.value)};function SX(a,b){this.c=a;this.g=b;this.f=yV(a,RX);this.a=new EV(1,[[2,5126]]);this.b=HV(a,[0,0,1,0,0,1,1,1])}function TX(a,b,c){var d=b.j,e=b.i,f=a.c,g=a.g,h=f.a.vb()+1-1;f.a.xa(h,b);g.V.set(h);g.Y.set(d,e);g.W.set(1);g.ha.set(d,e);g.Z.set(0,0);g.T.set(B(c)?c:1);g.S.set(0);g.U.set(1);FV(f,a.a);KV(f,a.b,a.a);b=hq(f);a.f.bind(b,g);f.drawArrays(5,0,4);iq(f);GV(f,a.a)};function UX(){this.value=0}UX.prototype.set=function(a){this.value=a};function VX(){this.value=0}VX.prototype.set=function(a){this.value=a};function WX(){this.value=new Float32Array(16)} +WX.prototype.set=function(a,b,c,d,e,f,g,h,k,l,m,n,p,q,t,v){this.value[0]=a;this.value[1]=b;this.value[2]=c;this.value[3]=d;this.value[4]=e;this.value[5]=f;this.value[6]=g;this.value[7]=h;this.value[8]=k;this.value[9]=l;this.value[10]=m;this.value[11]=n;this.value[12]=p;this.value[13]=q;this.value[14]=t;this.value[15]=v};function XX(a,b){for(var c=0;16>c;c++)a.value[c]=b[c]}function YX(){this.value=new Float32Array(2)}YX.prototype.set=function(a,b){this.value[0]=a;this.value[1]=b}; +function ZX(){this.value=new Float32Array(3)}ZX.prototype.set=function(a,b,c){this.value[0]=a;this.value[1]=b;this.value[2]=c};function $X(){this.value=new Float32Array(4)}$X.prototype.set=function(a,b,c,d){this.value[0]=a;this.value[1]=b;this.value[2]=c;this.value[3]=d};function aY(){this.L=new UX;this.O=new UX;this.P=new UX;this.S=new UX;this.T=new UX;this.U=new UX;this.V=new VX;this.W=new UX;this.Y=new YX;this.Z=new YX;this.ha=new YX;this.fa=new ZX;this.ga=new ZX;this.ia=new UX;this.ja=new ZX;this.pa=new ZX;this.ra=new ZX;this.va=new ZX;this.g=new ZX;this.h=new ZX;this.i=new WX;this.j=new UX;this.ya=new YX;this.Zb=new VX;this.Za=new UX;this.I=new UX;this.$a=new YX;this.ib=new $X;this.jb=new UX;this.u=new VX;this.v=new $X;this.Ba=new VX;this.Ca=new ZX;this.D=new VX; +this.G=new $X;this.M=new UX;this.l=new VX;this.J=new UX;this.Da=new UX;this.Ga=new UX;this.a=new WX;this.Bb=new UX;this.outline=new VX;this.b=new UX;this.H=new UX;this.m=new UX;this.Ia=new VX;this.Ja=new $X;this.Ka=new UX;this.qb=new UX;this.la=new UX;this.o=new $X;this.ea=new YX;this.hc=new UX;this.K=new VX;this.s=new $X;this.La=new UX;this.Oa=new ZX;this.Pa=new ZX;this.c=new UX;this.Qa=new $X;this.Ra=new YX;this.rb=new $X;this.sb=new $X;this.Hb=new VX;this.Ya=new YX;this.Sa=new UX;this.A=new VX; +this.B=new $X;this.text=new VX;this.Wa=new $X;this.C=new $X;this.f=0};function bY(a,b,c,d,e){if(b[d+1]==b[e+1]){var f=c;c=e;e=f}else b[c+1]==b[e+1]&&(f=d,d=e,e=f);b[c+1]!=b[d+1]&&(b[c+1]>b[d+1]&&(f=c,c=d,d=f),b[d+1]>b[e+1]&&(f=d,d=e,e=f),b[c+1]>b[d+1]&&(f=c,c=d,d=f));f=b[c];var g=b[d],h=b[e];c=b[c+1];d=b[d+1];b=b[e+1];c!=b&&(e=f+(d-c)/(b-c)*(h-f),cY(a,Math.min(e,g),h,Math.max(e,g),d,b),c!=d&&cY(a,Math.min(e,g),f,Math.max(e,g),d,c))} +function cY(a,b,c,d,e,f){var g=(c-b)/(f-e);c=(c-d)/(f-e);var h=Math.min(e,f);f=Math.max(e,f);h=Math.max(0,Math.floor(.999+h));for(f=Math.min(255,Math.floor(f));h<=f;h++){var k=h-e,l=b+g*k;k=d+c*k;l=Math.max(0,Math.floor(.999+l));for(k=Math.min(255,Math.floor(k));l<=k;l++)a[256*h+l]=255}};function dY(){this.a=new sI(0,!1)};function eY(){this.s=this.c=this.Zb=this.Ya=this.hc=this.ea=this.b=this.o=this.u=this.A=this.j=this.i=this.h=this.g=this.f=this.D=this.l=this.m=this.G=this.H=this.v=this.B=this.C=null;this.I={}}var fY="#define _b 8\n#define _c 8000\n#define _d "+QB+"\n#define _e 2\n#define _f 16\n#define _g 8\n#define _h vec4(0., 0., 0., 0.2)\n#define _i 2\n#define _j 9\n#define _k 6\n#define _l 3\n#define _m 0\n#define _n 1\n#define _o 2\n#define _p 4\n#define _q 5\n#define _r 12\n#define _s 0\n#define _t 8\n#define _u 2\n#define _v 1\n#define _w 22\n\n"; +eY.prototype.a=function(a,b){b="#define _a "+b.f+"\n";var c=this.I[b];c||(c=zV(a,fY+b+"precision highp float;uniform vec4 d,j;uniform sampler2D e;vec2 N(vec2 x,float B){float C=float(_r);x.y=C*x.y+B;return (x+.5)*d.zw;}\n#if _a==1\nuniform float h;varying vec3 i;\n#endif\nuniform vec3 k,l;uniform mat4 m;uniform float o,u,w;\n#if _a==1\nuniform mat4 p;vec3 O(vec3 B){const float C=6371010.;float D,E,F,G,H,I,J,K,L,M;D=B.x;E=exp(B.y);F=E*E;G=2.*E/(1.+F);H=(F-1.)/(1.+F);I=B.z*C*G;J=I+C;K=J*G*cos(D);L=J*G*sin(D);M=J*H;return vec3(K,L,M);}vec4 P(vec3 B){vec4 C,F;C=m*vec4(B,1);vec3 D,E;D=B;D/=o;D+=k+l;D.xy-=.5;D.y=-D.y;D*=3.141592653589793*2.;E=O(D);F=p*vec4(E,1);F/=F.w;C/=C.w;return mix(C,F,h);}vec3 Q(vec3 B){B/=o;B+=k+l;B.xy-=.5;B.y=-B.y;B*=3.141592653589793*2.;vec3 C=mat3(p)*O(B);return normalize(C);}\n#else\nvec4 P(vec3 B){return m*vec4(B,1);}\n#endif\nvec3 R(vec3 B,vec3 C){vec3 D=B-k+(C-l);return D*o;}vec3 S(vec3 B){vec3 C,D;C=vec3(j.x,j.y,0);D=B*j.w;D.xy*=1./float(_f);return R(C,D);}vec4 T(vec3 B){vec3 C=S(B);return P(C);}float U(vec4 B){float C,D;C=1./float(_w+1);D=1.-C-j.z*C;return B.z*C+B.w*D;}void V(vec3 j){\n#if _a==1\nvec3 B=S(j);i=Q(B);\n#endif\n}precision highp float;varying vec2 r;varying vec3 s;attribute vec2 t;uniform vec2 v,x;void main(){vec3 j=vec3(floor(t*32767.+.5),0);V(j);gl_Position=T(j);gl_Position.xy+=v*gl_Position.w;gl_Position.z=gl_Position.w*u;gl_Position.z=U(gl_Position);r=j.xy*w;vec2 B=N(x,float(_l));s=texture2D(e,B).rgb;}", +fY+b+"precision highp float;precision highp float;\n#if _a==1\nuniform float h;varying vec3 i;\n#endif\nfloat D(){\n#if _a==1\nfloat B,C;B=dot(i,vec3(-1.,1,-1.));C=clamp((B-.5)/4.+1.,.5,1.);return mix(1.,C,h);\n#else\nreturn 1.;\n#endif\n}precision highp float;varying vec2 r;varying vec3 s;uniform sampler2D A;void main(){float B,C;B=texture2D(A,r).a;if(B<.5)discard;C=D();gl_FragColor=vec4(s*C,1);}",["t"]),this.I[b]=c);this.c=c}; +eY.prototype.bind=function(a,b){this.a(a,b);if(this.s!=this.c){var c=this.c,d=function(b){return a.getUniformLocation(c,b)};this.C=d("a");this.B=d("b");this.v=d("c");this.H=d("d");this.G=d("e");this.m=d("f");this.l=d("g");this.D=d("h");this.f=d("j");this.g=d("k");this.h=d("l");this.i=d("m");this.j=d("n");this.A=d("o");this.u=d("p");this.o=d("q");this.b=d("u");this.ea=d("v");this.hc=d("w");this.Ya=d("x");this.Zb=d("A");this.s=this.c}a.useProgram(this.s);this.C&&a.uniform4fv(this.C,b.s.value);this.B&& +a.uniform4fv(this.B,b.o.value);this.v&&a.uniform1f(this.v,b.b.value);this.H&&a.uniform4fv(this.H,b.B.value);this.G&&a.uniform1i(this.G,b.A.value);this.m&&a.uniform4fv(this.m,b.v.value);this.l&&a.uniform1i(this.l,b.u.value);this.D&&a.uniform1f(this.D,b.c.value);this.f&&a.uniform4fv(this.f,b.C.value);this.g&&a.uniform3fv(this.g,b.g.value);this.h&&a.uniform3fv(this.h,b.h.value);this.i&&a.uniformMatrix4fv(this.i,!1,b.i.value);this.j&&a.uniform1f(this.j,b.j.value);this.A&&a.uniform1f(this.A,b.m.value); +this.u&&a.uniformMatrix4fv(this.u,!1,b.a.value);this.o&&a.uniform1i(this.o,b.l.value);this.b&&a.uniform1f(this.b,b.I.value);this.ea&&a.uniform2fv(this.ea,b.ea.value);this.hc&&a.uniform1f(this.hc,b.hc.value);this.Ya&&a.uniform2fv(this.Ya,b.Ya.value);this.Zb&&a.uniform1i(this.Zb,b.Zb.value)};function gY(a,b){this.a=a;this.j=b;this.i=yV(a,eY);this.c=new EV(3,[[2,5122]]);this.l=new ir(this.a,this.c.a,this.c.b,void 0);b=IV(-16,4112,8,-16,4112,8);b=new Int16Array(b);b=new Uint32Array(b.buffer);this.g=PV(this.l,b).a[0];this.f=a.createTexture();Uo(this.f,new Uint8Array([255,255,255,255]),1,1,6408,5121,0);this.h=new dY}function hY(){this.b=0;this.a=null}var iY=new eo;function jY(a,b,c){a.hc.set(1/4096);a.Zb.set(2);a.ea.set(b.Va.x,b.Va.y);wX(c,b.md,iY);a.Ya.set(iY.x,iY.y)} +gY.prototype.b=function(a,b){var c=a.a,d=a.data,e=d.a,f=this.a,g=0;if(!rI(d.getZoom(),b))return 2;d=a.data.A;var h;b=[];if(Gy(e)&&ly(Hy(e))){e=Hy(e).a;for(var k=a.data.b.a[2],l=0;l<e.length;l++){var m=e[l],n=m.getExtension(177034656);if(n&&(null==n.a?0:n.a)){g=k[l].za;if(null==m.c?0:m.c){var p=!0;break}null!=m.a&&b.push(ux(m))}}}if(b.length&&!d)a:{d=this.h;a=a.data.c;e=new Uint8Array(65536);for(k=0;k<b.length;k++){m=b[k];n=d.a;l=a;n.reset();LI(m,n,!1);m=n.h.subarray(0,n.b);if(0==m.length)m=null;else{n= +new Float32Array(2*m.length);for(var q=0;q<m.length;q++){var t=m[q];n[2*q+0]=(t<<16>>16)/l;n[2*q+1]=(t>>16)/l}m=n}if(!m){d=null;break a}n=m.length/6;if(0!=n)for(l=e,n=n?6*n:m.length,q=0;q<n;q+=6)bY(l,m,q,q+2,q+4)}d=new VQ(e,256,256,4)}d&&(h=new CT(d));if(!h&&!p)return 2;b=c.a;p=new hY;h&&(d=h.Yb().width,d=iO(b,d*d),b=b.c[d],Mo(b,33071),No(b,9729),Oo(b,9729),XQ(f,h),p.a=b);p.b=1-g/65535;c.ya=p;return 2};function kY(a,b){rc.call(this);this.v=1;this.a=a;this.b=new aY;this.D=new no(this);this.C=this.h=this.J=this.L=this.K=this.j=this.i=this.I=this.G=this.s=this.m=this.l=this.B=this.A=this.H=this.g=this.M=this.c=null;this.f=0;this.P=b;lY(this);a=this.a.getContext();this.D.cb(a,"webglcontextrestored",this.T,!1);this.D.cb(a,"webglcontextlost",this.S,!1)}F(kY,rc);var mY=[];function nY(a){return[a.c,a.H,a.A,a.g]}function oY(a){var b=[];b[0]=a.l;b[1]=a.B;b[2]=a.m;b[3]=a.s;b[4]=a.i;b[5]=a.j;return b} +function pY(a){return[a.G,a.I]}kY.prototype.S=function(){var a=this.a;Sq(a.b);Sq(a.a);Sq(a.f);Sq(a.c);Sq(a.g);this.dispatchEvent("webglcontextlost")};kY.prototype.T=function(){var a=this.a.getContext(),b=this.a.b;Tq(b,a);b.clear();b=this.a.a;Tq(b,a);b.clear();b=this.a.f;Tq(b,a);b.clear();b=this.a.g;Tq(b,a);b.clear();b=this.a.c;Tq(b,a);b.clear();lY(this);this.dispatchEvent("webglcontextrestored")}; +function qY(a,b){var c=a.a.b;Wq(c);for(var d=0;d<b.length;++d){var e=b[d],f=e.a,g=f.a;g&&(f.u&&f.u.Fa(g),f.A&&f.A.Fa(g));e.b&&(f=e.b.a,g=f.a)&&(f.u&&f.u.Fa(g),f.A&&f.A.Fa(g))}Yq(c);c=a.a.a;Wq(c);for(d=0;d<b.length;++d)e=b[d],f=e.a,g=f.a,f.c&&g&&f.c.Fa(g),e.b&&(f=e.b.a,g=f.a,f.c&&g&&f.c.Fa(g));Yq(c);c=a.a.c;Wq(c);for(d=0;d<b.length;++d)e=b[d],f=e.a,g=f.a,f.o&&g&&f.o.f.Fa(g),e.b&&(f=e.b.a,g=f.a,f.o&&g&&f.o.f.Fa(g));Yq(c);c=a.a.f;Wq(c);for(d=0;d<b.length;++d)e=b[d],f=e.a,g=f.a,f.o&&g&&f.o.Fa(g),e.b&& +(f=e.b.a,g=f.a,f.o&&g&&f.o.Fa(g));Yq(c);a=a.a.g;Wq(a);for(d=0;d<b.length;++d)e=b[d],f=e.a,g=f.a,f.H&&g&&f.H.Fa(g),e.b&&(f=e.b.a,g=f.a,f.H&&g&&f.H.Fa(g));Yq(a)} +function rY(a,b,c,d,e,f){var g=a.a.getContext(),h=a.b;if(g&&!g.isContextLost()){for(var k=!1,l=0;l<c.length;l++){var m=c[l];if(m.data.g||m.b&&m.b.data.g)k=!0}l=f.g&&!f.L;m=f.g&&!f.K&&!f.u;k=!f.M&&f.h&&k;var n=!f.v&&(!f.g||f.h),p=f.A;h.f=p?1:0;h.c.set(p?1:0);f.B=p||0!=d.o||0!=d.b;f.b=p?8:1;f.J=p?new rN(0,0):zN(d);f.m=AN(d);h.m.set(f.m);p=BN(d);XX(h.i,p);h.l.set(.2618<=Math.abs(d.b)?1:0);h.j.set(d.b);p=gG();var q=MJ();eP(d,p);OJ(q,p);XX(h.a,q);var t=a.a;p=t.getContext();q=a.b;p.a.Ua(null);Vq(t.b);Vq(t.a); +Vq(t.f);Vq(t.g);Vq(t.c);sY(e,c,f);f.h&&qY(a,c);tY(a);q.s.set(f.j,f.i,1/f.j,1/f.i);q.o.set(f.f,f.c,1/f.f,1/f.c);q.b.set(f.l);t=[0,0];var v=tX(e,t);p.a.xa(0,v);q.A.set(0);q.B.set(t[0],t[1],1/t[0],1/t[1]);uY(a,c);p=a.a.a;fr(p,1);a.b.u.set(1);a.b.v.set(p.c,p.a,1/p.c,1/p.a);for(p=f.J.start;p<=f.J.a;p++){q=f;t=h;var u=2*Math.PI;v=d.h/u+.5;var w=-d.i/u+.5,y=d.m/u;v-=p;u=Math.round(65536*v)/65536;var A=Math.round(65536*w)/65536,z=Math.round(65536*y)/65536;t.g.set(u,A,z);v=new Float32Array([v-u,w-A,y-z]); +t.h.set(v[0],v[1],v[2]);q.H=u+v[0];q.I=A+v[1];l&&(f.A&&(g.depthRange(0,1),q=a.J,t=a.a.getContext(),v=f,w=a.b,1==w.c.value&&(TV(t,v,3,3,1,1,1),FV(t,q.c),KV(t,q.f,q.c),t.b.Fb(!1),u=hq(t),q.b.bind(u,w),wX(t,v.md,AX),u.uniform2f(q.b.Ya,AX.x,AX.y),t.drawArrays(6,0,q.a/2),wX(t,v.G,AX),u.uniform2f(q.b.Ya,AX.x,AX.y),t.drawArrays(6,q.a/2,q.a/2),iq(t),t.b.Fb(!0),GV(t,q.c)),f.D||(q=a.L,t=a.a.getContext(),w=f,v=a.b,A=d,u=WF(),uG(A.j,A.l,A.f,u,1),u=1/((1+u[2])*Math.tan(A.g/2)),A=A.c/A.a,z=new Float32Array(4), +z[3]=1,RJ(v.a.value,z,z),y=z[0]/z[3],z=z[1]/z[3],u*u<(1-z)*(1-z)+A*(1-y)*A*(1-y)&&(TV(t,w,3,3,1,1,1),FV(t,q.a),KV(t,q.b,q.a),v.ya.set(y,z),v.O.set(A),v.Ka.set(u),t.b.Fb(!1),w=hq(t),q.c.bind(w,v),t.drawArrays(5,0,4),iq(t),t.b.Fb(!0),GV(t,q.a)))),vY(a,b,f,e));m&&(g.depthRange(.1,.2),q=a.g,t=b,v=f,w=q.h,u=q.f,fW(t)&&(FV(u,q.a),eW(q,v),TV(u,v,1,3,1,2,2),UV(u,v,1024),A=hq(u),q.c.bind(A,w),gW(q,A,t,q.c.b),TV(u,v,3,3,4,2,2),gW(q,A,t,q.c.b),q.g.bind(A,w),gW(q,A,t,q.g.c),iq(u),GV(u,q.a)));if(k)for(g.depthRange(0, +.1),q=a,t=c,v=f,w=q.a.getContext(),RV(w,v),w=0;2>w;w++)$W(q.l,t,v,w),QX(q.B,t,v,w),hX(q.m,t,v,w),lX(q.s,t,v,w),vW(q.i,t,v,w),DW(q.j,t,v,w);if(n){q=a.h;t=b;v=f;w=q.a;u=q.o;var C=v.l,I=v.s,S=v.b;A=!(v.g||v.h);y=v.zoom;z=v.O;if(q.l!=C||q.g!=I||q.m!=S)pW(q,C,I,S),q.l=C,q.g=I,q.m=S;u.I.set(0);u.ea.set(0,0);u.K.set(3);w.a.xa(3,q.h);FV(w,q.f);KV(w,q.i,q.f);TV(w,v,3,1,1,2,2);C=hq(w);q.c.bind(C,u);qW(q,C,t,v,A,y,z);iq(w);GV(w,q.f)}}f.g&&!f.D&&(g.depthRange(0,1),b=yN(d),0<b&&b<d.a&&JX(a.K,a.a.getContext(), +f,a.b,d.a-b));gr(a.a.a)}}function uY(a,b){for(var c=a.f=0;c<b.length;++c){var d=b[c];rO(d);var e=d.a.a;a.f+=e.a;d.b&&!UM(d.b.data)&&(e=d.b.a.a,a.f+=e.a)}}function tY(a){a=a.a.getContext().a;for(var b=0;6>=b;++b)a.xa(b,null)} +function vY(a,b,c,d){var e=a.a.getContext();b=b.filter(function(a){return a.a.length&&a.a[0].a.length});for(var f=0;f<b.length;++f){var g=b[f],h=.8/b.length,k=1-h*f;e.depthRange(k-h,k);h=[];for(k=0;k<g.a.length;++k)for(var l=g.a[k],m=0;m<l.a.length;++m){var n=l.a[m];n.data&&h.push(n)}h.length&&wY(a,h,c,d)}RV(e,c)} +function sY(a,b,c){if(b.length){var d=a.a;++d.a;d.c=0;pX(a.a,0);xX(a,[c.md,c.G]);for(c=0;c<b.length;++c){d=b[c];var e=d.a.va;e&&e.length&&xX(a,e);e=d.a.f;0<e.c&&(e=JR(e),e.length&&xX(a,e));(d=d.b&&d.b.a.f)&&0<d.c&&(e=JR(d),e.length&&xX(a,e))}}} +function wY(a,b,c,d){var e=a.a.getContext();if(c.B){UV(e,c,1024);e=a.M;var f=e.h,g=e.j,h=e.i;if(e.f!=c.b){var k=JV(f,0,4096,c.b,0,4096,c.b);e.b=k.buffer;e.c=k.size;e.f=c.b}FV(f,e.a);KV(f,e.b,e.a);TV(f,c,1,1,3,2,2);g.K.set(3);g.L.set(1);g.M.set(1);g.I.set(0);g.ea.set(c.Va.x,c.Va.y);f.a.xa(3,e.g);k=hq(f);h.bind(k,g);for(g=0;g<b.length;g++){var l=b[g].a;f.stencilFunc(516,l.Z,255);k.uniform4f(h.b,l.g,l.h,l.m,l.b);f.drawArrays(4,0,e.c)}iq(f);GV(f,e.a)}e=a.c;d=d.b;for(f=0;f<b.length;f++){l=k=null;var m= +null;if(b[f].b){h=b[f].b;k=b[f];g=h.a.ga;var n=h.a.Ba;l=k.a.ga;m=k.a.Ba}else h=b[f],g=h.a.ga,n=h.a.Ba;c.u&&(n=g=null);if(g||l||n||m)if(e.c.push(h.a),e.f.push(g),e.h.push(n),e.g.push(l),e.i.push(m),h&&VV(h,d,c.zoom)||k&&VV(k,d,c.zoom))e.j.push(h.a),e.l.push(g),e.o.push(n),e.m.push(l),e.s.push(m)}YV(a.c,c,!1,!1);YV(a.c,c,!1,!0);d=a.G;e=d.f;l=d.j;f=d.i;n=!1;for(h=0;h<b.length;h++)if(k=yW(b[h],c),g=zW(b[h]),k||g){n=!0;break}if(n){TV(e,c,3,3,2,2,2);d.h!=c.b&&(h=JV(e,-8,4104,c.b,-8,4104,c.b),d.g=h.buffer, +d.a=h.size,d.h=c.b);l.K.set(3);l.L.set(1);l.M.set(1);l.ea.set(0,0);FV(e,d.c);KV(e,d.g,d.c);n=hq(e);f.bind(n,l);for(h=0;h<b.length;++h)if(k=yW(b[h],c),g=zW(b[h]),k||g){l=b[h].a;n.uniform4f(f.b,l.g,l.h,l.m,l.b);SV(e,c,l.Z,l.g,l.h,l.b);if(k)for(l=0;l<k.length;l++)e.a.xa(3,k[l].Xb),n.uniform1f(f.c,k[l].a),e.drawArrays(4,0,d.a);if(g)for(l=0;l<g.length;l++)e.a.xa(3,g[l].Xb),n.uniform1f(f.c,g[l].a),e.drawArrays(4,0,d.a)}iq(e);GV(e,d.c)}YV(a.c,c,!0,!1);d=a.I;e=d.a;g=d.j;f=d.c;h=d.i;TV(e,c,3,3,2,2,2);FV(e, +f);jY(g,c,e);k=hq(e);h.bind(k,g);for(g=0;g<b.length;++g)if(m=b[g],m.b?(l=m.b.a.ya,n=m.a.ya):(l=m.a.ya,n=null),l||n)m=m.a,k.uniform4f(h.f,m.g,m.h,m.m,m.b),SV(e,c,m.Z,m.g,m.h,m.b),l&&(e.a.xa(2,l.a||d.f),k.uniform1f(h.b,l.b),MV(e,f,d.g)),n&&(e.a.xa(2,n.a||d.f),k.uniform1f(h.b,n.b),MV(e,f,d.g));iq(e);GV(e,f);d=a.A;e=d.c;g=d.g;f=d.a.f;h=d.f;l=d.i;n=!1;for(k=0;k<b.length;k++)if(m=b[k].b,b[k].a.I||m&&m.a.I){n=!0;break}if(n){TV(e,c,3==c.s?5:3,3,2,2,2);FV(e,f);LV(e,l,f);l=hq(e);h.bind(l,g);for(k=0;k<b.length;k++)if(b[k].b? +(g=b[k].b.a.I,n=b[k].a.I):(g=b[k].a.I,n=null),g||n)m=b[k].a,l.uniform4f(h.c,m.g,m.h,m.m,m.b),SV(e,c,m.Z,m.g,m.h,m.b),OV(e,f,g,n);iq(e);GV(e,d.a.f)}VW(a.H,b,c);YV(a.c,c,!0,!0);a=a.c;a.c=[];a.f=[];a.h=[];a.g=[];a.i=[];a.j=[];a.l=[];a.o=[];a.m=[];a.s=[]} +function lY(a){var b=a.a.getContext(),c=a.b,d=a.P,e=a.a.c,f=a.a.b,g=a.a.f,h=a.a.g;a.c=new XV(b,c);a.I=new gY(b,c);a.g=new dW(b,c);a.h=new nW(b,c);a.i=new uW(b,c,f,d);a.G=new xW(b,c);a.j=new CW(b,c,f);a.H=new UW(b,c,f);a.l=new ZW(b,c);a.m=new gX(b,c,g,e);a.s=new kX(b,c,h,d);a.A=new DX(b,c);a.L=new LX(b,c);a.J=new zX(b);a.K=new IX(b);a.M=new MX(b,c);a.B=new PX(b,c);a.C=new SX(b,c)};function xY(a,b,c,d,e,f,g){dQ.call(this,a,b,c,d,e,f,g);this.c=d}F(xY,dQ);xY.prototype.f=function(){return new cQ(this.c.wd())};xY.prototype.g=function(){return this.c};xY.prototype.getContext=function(){return this.c.getContext()};xY.prototype.X=function(){this.c.$();xY.R.X.call(this)};function yY(){this.h=this.g=!0;this.A=this.K=this.D=this.L=this.M=this.O=this.v=!1;this.T=0;this.S=this.P=45;this.m=this.zoom=this.I=this.H=0;this.J=new rN(0,0);this.a=new eo(0,0);this.Va=new eo(0,0);this.b=1;this.B=!1;this.i=this.j=this.c=this.f=0;this.l=1;this.s=0;this.clearColor=ZH;this.o=new oq(0,0,0,0);this.C=1;this.u=!1;this.G=this.md=0};function zY(a){this.b=a;this.c=-1;this.a=1}function AY(a,b){var c=a.c!=b;a.c=b;c?(a.a-=.2,0>=a.a&&(a.a=0),a.b()):(a.a+=.2,1<=a.a?a.a=1:a.b());return a.a};function BY(a,b,c){this.h=a;this.i=b;this.l=c;this.f=new SF;this.j=1;this.c=0;this.b={};this.g=this.a=0}BY.prototype.capture=function(a){jQ(this.h,this.f);this.j=this.i.f;this.c=0;this.b={};for(var b=this.a=0;b<a.length;++b){var c=a[b];0<c.a.B&&(this.c++,this.b[c.a.B]=!0);c.a.c&&c.a.c.f>this.a&&(this.a=c.a.c.f);c.b&&c.b.a.c&&c.b.a.c.f>this.a&&(this.a=c.b.a.c.f);c.b&&0<c.b.a.B&&(this.c++,this.b[c.b.a.B]=!0)}this.g=this.l.o};var CY=new SF; +function DY(a,b){jQ(a.h,CY);if(!TF(CY,a.f)||a.j!=a.i.f||a.g!=a.l.o)return!1;for(var c=0,d=0;d<b.length;++d){var e=b[d];if(0<e.a.B){if(!a.b[e.a.B])return!1;c++}if(e.b&&0<e.b.a.B){if(!a.b[e.b.a.B])return!1;c++}if(e.a.c&&e.a.c.f>a.a||e.b&&e.b.a.c&&e.b.a.c.f>a.a)return!1}return c!=a.c?!1:!0};function EY(){this.b=this.c=this.a=null;this.height=this.width=0} +function FY(a,b,c,d,e){if(!a.a||!!a.c!=e||a.width!=c||a.height!=d){var f=b.a.f,g=b.a.h,h=Po(b.b),k=b.a.c[h-33984];a.a&&b.deleteFramebuffer(a.a);a.c&&b.deleteRenderbuffer(a.c);a.b&&b.deleteTexture(a.b);var l=b.createFramebuffer();b.bindFramebuffer(36160,l);var m=null;e&&(m=b.createRenderbuffer(),b.bindRenderbuffer(36161,m),b.renderbufferStorage(36161,34041,c,d),b.framebufferRenderbuffer(36160,33306,36161,m));e=b.createTexture();No(e,9728);Oo(e,9728);Mo(e,33071);b.bindTexture(3553,e);Uo(jq(b,3553), +null,c,d,6408,5121,0);b.framebufferTexture2D(36160,36064,3553,e,0);a.a=l;a.c=m;a.b=e;a.width=c;a.height=d;f&&b.bindFramebuffer(36160,f);g&&b.bindRenderbuffer(36161,g);B(h)&&B(k)&&(b.activeTexture(h),b.bindTexture(3553,k))}}EY.prototype.bind=function(a){a.bindFramebuffer(36160,this.a);a.viewport(0,0,this.width,this.height)};function GY(a,b){a=a.toString();b&&(a+="-"+b);return a};function HY(a,b,c,d,e,f){this.a=a;this.text=b;this.width=c;this.height=d;this.b=e;this.name=f}function IY(a,b,c,d){JW.call(this,a.b);this.g=b;this.f=[];this.h={};this.l=-1;this.m=d;for(a=0;a<c.length;++a)b=c[a],(d=this.c)&&b.height>d.v||this.f.push(b)}F(IY,JW);r=IY.prototype;r.Ob=function(){return this.f.length};r.ac=function(a){return this.f[a].name};r.$b=function(a){a=this.f[a];var b=RA(this.g.a,a.a);return b&&fA(b,this.m)?Zs(fA(b,this.m),a.width,a.height,a.b,a.text):null}; +r.zb=function(a){return this.f[a].width+1};r.yb=function(a){a=4*Math.ceil((this.f[a].height+1)/4);8>a&&(a=8);return a};r.Na=function(a){if(a=IY.R.Na.call(this,a))for(var b=0;b<this.f.length;++b){var c=this.f[b],d=GY(c.a,c.text);-1!=this.b[b]&&(this.h[d]=new pq(KW(this,b),LW(this,b),c.width,c.height))}return a};r.Pb=function(){return this.l!=this.g.c||IY.R.Pb.call(this)};r.Fa=function(a){IY.R.Fa.call(this,a);this.l=this.g.c};function wW(a,b,c,d){b=GY(b,c);0!=a.a||a.Na(d);return a.h[b]};var JY=null;function KY(a){1500>a&&(a=1500);var b=JY;if(!b||b.length<a)b=JY=new Float32Array(a);return b} +function LY(a,b,c,d,e){var f=c.left,g=c.top,h=c.width,k=c.height,l=Math.floor(c.width/2),m=Math.floor(c.height/2);c=h;for(var n=0,p=k,q=0,t=0;t<k;++t)for(var v,u=0;u<h;++u){var w=f+u,y=g+t;w=a[4*(w+b*y)+3];0<w&&(u<c&&(c=u),u>n&&(n=u),t<p&&(p=t),q=t)}e.left=-4-l;e.top=-4-m;e.width=h+8;e.height=k+8;if(c>n||p>q)return d.left=-l,d.width=h,d.top=-1,d.height=1,n=4*Math.ceil(e.width/4),e=new Uint8Array(n*e.height);c-=4;n+=4;p-=4;q+=4;d.left=c-l;d.top=p-m;d.width=n-c+1;d.height=q-p+1;d=n-c+1;l=q-p+1;m=KY(d* +l);var A=-c,z=-p;for(t=p;t<=q;++t){var C=0,I=-100;v=d*(t+z);for(u=c;u<=n;++u){0>u||u>=h||0>t||t>=k?w=0:(w=f+u,y=g+t,w=a[4*(w+b*y)+3]);var S=u+A;if((w==C||1.5>u-I)&&0==w%255)m[S+v]=255==w?u-I:I-u;else{if(w!=C){C=0<w-C?1:-1;var ca=I;I=u+C*(.5-w/255);for(var Z=u-1;Z>=c&&I-Z<=Z-ca;Z--)y=Z+A+v,C*m[y]<Z-I&&(m[y]=C*(Z-I))}m[S+v]=(w-128)/255}C=w}}n=4*Math.ceil(e.width/4);e=new Uint8Array(n*e.height);for(q=0;q<l;++q)for(t=q+p,v=d*q,A=0;A<d;++A){u=A+c;0>u||u>=h||0>t||t>=k?w=0:(w=f+u,y=g+t,w=a[4*(w+b*y)+3]); +if(255==w||0==w){u=w?1:-1;y=A+v;y=u*m[y];w=y*y;for(z=1;6>z&&z*z<w;z=-z+(0<z?0:1))0>q+z||q+z>=l||(y=A+d*(q+z),y=u*m[y],0>=y?(-.5>y&&(y=-.5),y=Math.abs(z)+y,y*=y):y=z*z+y*y,y<w&&(w=y));u=u*Math.sqrt(w)*12+128}else u=12*(w-128)/255+128;0>u&&(u=0);255<u&&(u=255);e[4+c+A+n*(4+p+q)]=u+.5}return e};function MY(a,b){this.b=a;this.a=this.b.getContext("2d");this.c=b}function NY(){this.b=this.a=0;this.text=""}function OY(a){this.a=new NY;this.f=a;this.height=this.width=this.c=this.b=0}var PY={},QY={},RY={};function SY(a,b,c){QY[a]=QY[a]||{};QY[a][b]=QY[a][b]||{};var d=QY[a][b][c];if(!B(d)){var e=(aX++).toString();bX[e.toString()]=new dX;d=QY[a][b][c]=e;var f=new NY;f.a=a;f.b=b;f.text=c;PY[e]=f}return d} +function TY(a,b,c){var d=UY,e=SY(a,b,c);if(!(bX[e]||null).data){var f=RY[e];f||(a=qL(a,b,d.c),d.a.font!=a&&(d.a.font=a),f=Math.ceil(d.a.measureText(c).width)," "!=c&&(f+=2),RY[e]=f)}return e}function VY(a,b){for(var c=0,d=0,e=0,f=0;f<a.length;f++){var g=a[f],h=g.f,k=g.a||new NY,l=PY[h];k.a=l.a;k.b=l.b;k.text=l.text;h=2*(RY[h]+4);e+h>=b&&(d+=c,e=c=0);k=2*g.a.a+4;k*=2;l=d+k/2;l-d+k/2>c&&(c=l-d+k/2);g.width=h;g.height=k;g.b=e;g.c=d;e+=h}a=d;0<e&&(a+=c);return new fo(b,a)} +function WY(a,b){var c=a.a;c.save();c.scale(2,2);c.fillStyle="rgba(255, 255, 255, 1)";c.textAlign="center";c.textBaseline="middle";for(var d=-1,e=0,f=0;f<b.length;f++){var g=b[f],h=g.b+g.width/2,k=g.c+g.height/2;g=g.a;if(g.a!=d||g.b!=e)d=g.a,e=g.b,c.font=qL(d,e,a.c);c.fillText(g.text,h/2,k/2)}c.restore()} +function XY(a,b,c){for(var d=0;d<a.length;d++){var e=a[d],f=bX[e.f]||null;if(!f||!f.data){var g=new pq(0,0,0,0),h=new pq(0,0,0,0);e=LY(b,c,new pq(e.b,e.c,e.width,e.height),g,h);f.data=e;f.b=g;f.a=h}}};function YY(a,b){JW.call(this,b);this.f=[];this.g={}}F(YY,JW);function ZY(a,b){B(a.g[b])||(a.g[b]=a.f.length,a.f.push(b))}function $Y(a,b){b=a.g[b];return-1!=a.b[b]?new eo(KW(a,b)+(MW(a,b)>>1),LW(a,b)+(NW(a,b)>>1)):null}r=YY.prototype;r.Ob=function(){return this.f.length};r.$b=function(a){return(bX[this.f[a]]||null).data};r.zb=function(a){return 8*(Math.ceil((bX[this.f[a]]||null).a.width/8)|1)};r.yb=function(a){return 12*(Math.ceil((bX[this.f[a]]||null).a.height/12)|1)};r.ac=function(a){return this.f[a]}; +r.Fa=function(a){0!=this.a||this.Na(a);if(this.Pb()){a=this.Ob();for(var b=0;b<a;b++){var c=bX[this.f[b]]||null;c.data&&OW(this,b,MW(this,b)/2+c.a.left,NW(this,b)/2+c.a.top,c.a.width,c.a.height,c.data)}this.j=this.c.A;this.a=2}};function aZ(a,b,c,d){LJ.call(this,a,b);this.c=!1;this.a=c;this.b=d;this.f=0}F(aZ,LJ);function bZ(a,b,c,d,e,f,g){JW.call(this,e);this.s=a;this.l=b;this.g=c;this.m=d;this.u=g;this.f=new YY(a,f);this.h=[];this.o=[]}F(bZ,JW);function cZ(a,b){this.a=a;this.b=b;this.c=0;this.kd=null}var dZ=new Uint8Array(2048),UY=null;r=bZ.prototype;r.Ob=function(){return this.h.length};r.ac=function(){};r.zb=function(a){return this.h[a].c};r.yb=function(){return 2}; +r.$b=function(a){var b=this.zb(a),c=this.yb(a),d=dZ;d.length<b*c*4&&(d=dZ=new Uint8Array(b*c*4));for(var e=0;e<b*c*4;e++)d[e]=0;c=this.h[a];if(tu(c.a)){a=d;c=c.a;e=uu(c);for(var f=0;f<e;++f){var g=wu(c)?xu(c,f)/8:0,h=a,k=b;var l=vu(c,f);var m=f,n=EL(this.g,l);l=(bX[n]||null).a;l=new pq(l.left/2+2,l.top/2+2,l.width/2-4,l.height/2-4);(n=$Y(this.f,n))&&eZ(m,n,l,h,k,2+g)}}else for(a=d,h=su(c.a),f=CK(this.m,c.b),k=this.g.getZoom(),c=hA(f,k),e=gA(f,k),f=iA(f,k)*c,h=fZ(h)?[h]:h.split(""),k=2,g=0;g<h.length;g++)if(l= +SY(c,e,h[g]),m=cX(l))if(l=$Y(this.f,l))eZ(g,l,m,a,b,k),k+=m.width,k+=f,k+=1;return d};r.Na=function(a){0!=this.f.a||this.f.Na(a);if(a=bZ.R.Na.call(this,a))for(var b=0;b<this.h.length;b++)if(-1!=this.b[b]){var c=this.h[b].kd;c.c=!0;c.a=KW(this,b);c.b=LW(this,b)}return a};r.Sb=function(){bZ.R.Sb.call(this);0!=this.f.a&&this.f.Sb()};var gZ=new pq(0,0,0,0); +bZ.prototype.Rc=function(){if(!UY){var a=Math.min(this.s.i+1,8193);this.l.height=64;this.l.width=a;UY=new MY(this.l,this.u)}a=this.g.a;if(Jy(a)&&py(Ky(a))){var b=[],c=Ky(a).a;for(a=0;a<c.length;a++){var d=c[a];if(null!=d.c||null!=d.b&&gu(Eu(d)))for(var e=Cu(d).a,f=0;f<e.length;++f){var g=e[f],h=AL(this.g,a,0,f);d=new cZ(g,h);this.h.push(d);this.o[h]=d;if(tu(g))for(d=d.a,g=uu(d),h=0;h<g;++h){var k=vu(d,h),l=EL(this.g,k);B(this.f.g[l])||(ZY(this.f,l),bX[l]||hZ(this,l,k))}else for(g=b,h=su(d.a),k=CK(this.m, +d.b),l=this.g.getZoom(),d=hA(k,l),k=gA(k,l),h=fZ(h)?[h]:h.split(""),l=0;l<h.length;l++){var m=TY(d,k,h[l]);B(this.f.g[m])||(ZY(this.f,m),g.push(m))}}}d=UY;a=[];for(c=0;c<b.length;++c)e=b[c],PY[e]&&((bX[e]||null).data||a.push(new OY(e)));a.length&&(b=VY(a,d.b.width),c=d.b,c.width<b.width&&(c.width=b.width),c.height<b.height&&(c.height=b.height),d.a.clearRect(0,0,b.width,b.height),WY(d,a),d=d.a.getImageData(0,0,b.width,b.height),XY(a,d.data,d.width));for(a=0;a<this.h.length;++a){b=d=this.h[a];if(tu(d.a)){f= +e=c=0;g=d.a;h=uu(g);k=Dy(this.g.a);for(l=0;l<h;++l){var n=ay(k,vu(g,l));m=Xx(n)/2;n=Yx(n)/2;m>c&&(c=m);n>e&&(e=n);n=wu(g)?xu(g,l)/8:0;m+=n;m>f&&(f=m)}e=new aZ(f+4,e,0,0);e.f=c;c=e}else{l=su(d.a);f=CK(this.m,d.b);g=this.g.getZoom();c=hA(f,g);e=gA(f,g);g=iA(f,g)*c;h=5;k=f=0;l=fZ(l)?[l]:l.split("");for(m=0;m<l.length;m++){n=SY(c,e,l[m]);var p=cX(n);n=p.width;p=2*Math.max(-p.top,p.height+p.top)+1;f=n>f?n:f;k=p>k?p:k;h+=n+g+1}c=new aZ(h,k,0,0);c.f=f}b.kd=c;d.c=2*Math.ceil(d.kd.width)+1}}}; +function hZ(a,b,c){var d=new dX;bX[b]=d;b=BL(a.g);b.Qb()&&b.Ib(2);b=b.Yb();a=ay(Dy(a.g.a),c);gZ.left=Vx(a);gZ.top=Wx(a);gZ.width=Xx(a);gZ.height=Yx(a);a=new pq(0,0,0,0);c=new pq(0,0,0,0);b=LY(b.data,b.width,gZ,a,c);d.data=b;d.b=a;d.a=c} +function eZ(a,b,c,d,e,f){var g=a%2,h=f+-c.left;a=b.x;b=b.y;a=a/8-.5;b=b/12-.5;var k=Math.floor(2*(f-2));h*=2;c=Math.ceil(2*(f+c.width+2));k++;h++;c++;k=Math.max(k,0);c=Math.min(c,e);f=2*g+4*k;e=4*e+2*g+4*k;h-=k+.5;g=Math.round(256*(h+128))>>8;for(var l=Math.round(256*(h+128))&254;k<c;++k)Math.abs(h)<=Math.abs(d[f+0]+d[f+1]/256-128)&&(d[f+0]=g,d[f+1]=l,d[e+0]=a,d[e+1]=b),f+=4,e+=4,h--,g--} +function fZ(a){for(var b=0;b<a.length;++b){var c=a.charCodeAt(b||0);(c=1424<=c&&1792>c)||(c=a.charCodeAt(b||0),c=!(0<=c&&1536>c||12288<=c&&65520>c));if(c)return!0}return!1}bZ.prototype.Tb=function(a){return(a=this.o[a])?a.kd:null};function iZ(a,b,c,d){JW.call(this,c);c=wy(a.a);this.g=a;this.m=b;this.l=nI(c);this.o=d;this.h=Math.ceil(2*this.l);this.f=[];this.s=[]}F(iZ,JW);function lZ(a,b){this.f=a;this.g=b;this.b=this.a=0;this.c=null}var mZ=new Uint8Array(7E3),nZ=null;r=iZ.prototype;r.Ob=function(){return this.f.length};r.ac=function(){};r.zb=function(a){return this.f[a].a};r.yb=function(a){return this.f[a].b}; +r.$b=function(a){a=this.f[a];if(tu(a.f)){var b=this.g.a,c=BL(this.g);c.Qb()&&c.Ib(2);c=c.Yb();var d=vu(a.f,0);b=ay(Dy(b),d);a=oZ(c.data,c.width,Vx(b),Wx(b),Xx(b),Yx(b),a.a,a.b,this.h)}else{b=su(a.f);c=this.g.getZoom();var e=CK(this.m,a.g);d=hA(e,c)*this.l;e=gA(e,c);c=pZ().getContext("2d");d=qL(d,e,this.o);c.font!=d&&(c.font=d);d=a.a;a=a.b;c.textBaseline="middle";c.textAlign="left";c.clearRect(0,0,d,a);c.fillText(b,this.h,a/2);b=c.getImageData(0,0,d,a);a=oZ(b.data,b.width,0,0,d,a,d,a,0)}return a}; +r.Tb=function(a){return(a=this.s[a])?a.c:null};function pZ(){nZ||(nZ=go("canvas"),nZ.width=512,nZ.height=128);return nZ} +r.Rc=function(){var a=this.g.a;if(Jy(a)&&py(Ky(a))){for(var b=Ky(a).a,c=this.g.getZoom(),d=0;d<b.length;d++){var e=b[d];if(null!=e.b&&!gu(Eu(e)))for(var f=null!=e.a?2:1,g=0;g<f;++g)for(var h=0==g?Cu(e):Du(e),k=0;k<(h.a?h.a.length:0);++k){var l=AL(this.g,d,g,k),m=CK(this.m,l),n=h.a[k];if(!fA(m,c)&&(tu(n)||null!=n.b)){var p=new lZ(n,l);this.f.push(p);this.s[l]=p}}}b=pZ().getContext("2d");e=this.h;f=this.l;for(d=0;d<this.f.length;d++)p=this.f[d],n=p.f,tu(n)?(m=vu(n,0),n=ay(Dy(a),m),m=Xx(n),n=Yx(n),p.c= +new aZ(m/f,n/f,0,0),p.a=2*e+m,p.b=2*e+n):(g=su(n),m=CK(this.m,p.g),n=hA(m,c)*f,0==n&&(n=2),m=gA(m,c),m=qL(n,m,this.o),b.font!=m&&(b.font=m),m=Math.ceil(b.measureText(g).width),p.c=new aZ(m/f,n/f,0,0),p.a=2*e+m,p.b=2*Math.ceil((2*e+1.3*n)/2)),p.a=4*Math.ceil(p.a/4)}}; +function oZ(a,b,c,d,e,f,g,h,k){var l=g-(k+e),m=h-(k+f),n=mZ;h*=g;n.byteLength<h&&(n=mZ=new Uint8Array(h));for(var p=h=0;p<k*g;p++)n[h++]=0;for(var q=0;q<f;q++){for(p=0;p<k;p++)n[h++]=0;var t=(d+q)*b*4+4*c+3;for(p=0;p<e;p++)n[h++]=a[t],t+=4;for(p=0;p<l;p++)n[h++]=0}for(p=0;p<m*g;p++)n[h++]=0;return n}r.Na=function(a){if(a=iZ.R.Na.call(this,a))for(var b=0;b<this.f.length;b++)if(-1!=this.b[b]){var c=KW(this,b),d=LW(this,b),e=this.f[b];c+=this.h;d+=e.b/2;e.c.c=!0;e.c.a=c;e.c.b=d}return a};function qZ(a,b,c,d){vM.call(this,c);this.c=a;this.v=b;this.m=d;this.s=go("canvas")}F(qZ,vM);qZ.prototype.j=function(a){var b=a.a.a,c=a.a.f,d=a.a.o;d||(d=new bZ(this.c.getContext(),this.s,a.data,c,this.c.f,this.c.c,this.m),d.Rc(),a.a.o=d,a.a.V=d);0!=d.a||d.Na(b);d=a.a.H;d||(d=new iZ(a.data,c,this.c.g,this.m),d.Rc(),a.a.H=d,a.a.Y=d);0!=d.a||d.Na(b)}; +qZ.prototype.g=function(a){for(var b=a.a.c,c=a.a.v,d=0;d<c.length;++d)for(var e=c[d].a,f=0;f<e.length;f++){var g=e[f].label;rZ(b,e[f].a,g.f,lK(g))}a=a.a;if(!a.u){b=a.m;c=a.la;d={};e=[];for(f=0;f<a.v.length;++f)if(g=a.v[f].c,4==g||5==g)for(var h=a.v[f].a,k=0;k<h.length;k++){var l=h[k],m=a.f.a[l.a],n="";if(4==g){var p=l;n=p.text}else p=l;var q=GY(m,n);!d[q]&&(d[q]=!0,q=fA(CK(a.f,l.a),b))&&(l=q.b||c,q=q.a,""!=q&&(q+=":"+l+":"+n),e.push(new HY(m,n,p.g.width,p.g.height,l,q)))}e.length&&(a.u=new IY(this.c, +this.v,e,b))}};function sZ(a,b){this.a=a;this.b=b}sZ.prototype.$=function(){this.a.lg(this.b);this.a=null};sZ.prototype.O=function(){return null==this.a};function tZ(a,b,c,d,e,f){qZ.call(this,a,b,c,d);this.h=e;this.o=f;this.a=WF();this.f=new Float64Array(4);this.l=[];this.i=!1}F(tZ,qZ);function uZ(a,b){a.i=b}tZ.prototype.b=function(a){tZ.R.b.call(this,a);vZ(this,a)}; +function vZ(a,b){if(0==b.a.ia&&!a.i)if(b.data.g){var c=b.a.j;if(0==c.length)b.a.ia=2;else{b.a.ia=1;var d=b.data,e=[],f=[],g=0,h=0;a.f.length<c.length&&(a.f=new Float64Array(c.length));for(var k=0;k<c.length;k++){var l=c[k],m=0,n=0;l.b?(m=l.b.a,n=l.b.b):l.a&&(m=gL(l.a,l.a.f),n=hL(l.a,l.a.f));m=m/256+tK(d);n=n/256+uK(d);zG(m,n,d.getZoom(),a.a);uG(a.a[0],a.a[1],0,a.a);m=a.h.ud();isFinite(m)?(a.f[h]=m,a.l[h]=k,h++):(e[2*g]=a.a[0],e[2*g+1]=a.a[1],f[g]=k,g++);l.s=!0}wZ(a,b,a.l,new Float64Array(a.f.buffer, +0,h));0<e.length?(c=new Float64Array(e),c=a.h.jg(c,function(c){b.a.a&&oO(b.a);c=wZ(a,b,f,c);a.o(b);c&&(b.a.fa.$(),b.a.fa=null,b.a.ia=2)}),b.a.fa=new sZ(a.h,c)):b.a.ia=2}}else b.a.ia=2}function wZ(a,b,c,d){var e=b.a.j;b=b.data;var f=a.a,g=tK(b)+.5,h=uK(b)+.5;zG(g,h,b.getZoom(),f);uG(f[0],f[1],f[2],f);a=wG(a.a[1]);b=tN/(1<<b.getZoom())/256;a/=b;b=!0;for(f=0;f<d.length;f++)g=d[f],h=e[c[f]],isFinite(g)?h.b?(h.b.altitude=g*a,h.s=!1):h.a&&(h.a.altitude=g*a,h.s=!1):b=!1;return b};function xZ(a,b,c){JW.call(this,a.a);this.g=c;this.m=a.getContext().i;this.l=PQ(b.b);this.f=0;a=new Uint8Array(this.zb(0)*this.yb(0)*4);for(b=0;b<this.l;++b)vX(GK(this.g,b),a,4*b,this.m);this.h=a}F(xZ,JW);var yZ=0;xZ.prototype.Ob=function(){return 1};xZ.prototype.$b=function(){return this.h};xZ.prototype.zb=function(){return Math.max(Math.ceil(this.l/this.yb(0)),1)};xZ.prototype.yb=function(){return 16}; +function zZ(a){var b=a.g.i;b.length&&(yZ++,a.f=yZ);b=b.concat(a.g.j);for(var c=0;c<b.length;++c){var d=b[c],e=a;vX(GK(a.g,d),e.h,4*d,e.m);2==e.a&&(e.a=1)}}function ZV(a,b){var c=a.zb(0);return new eo(KW(a,0)+b%c,LW(a,0)+Math.floor(b/c))}function rZ(a,b,c,d){var e=0;0<c&&(e|=31*c);d&&(e|=32);a.h[4*b]=e;2==a.a&&(a.a=1)};function AZ(a){this.b=a;this.Xb=null;this.a=0};function BZ(a,b,c,d,e,f,g,h){this.f=h.o;this.o=a;this.g=b;this.A=c;this.B=d;this.b=e;this.l=f;this.c=g;this.v=a.getContext();this.u=a.getContext().Zc();this.s=h.i;this.a=[this.Qf,this.Fe,this.Ee,this.hf,this.Ke,this.Gd,this.Jd,this.Fd,this.Id,this.Hd,this.Kd];this.h=[this.a.indexOf(this.Ke),this.a.indexOf(this.Gd),this.a.indexOf(this.Jd),this.a.indexOf(this.Fd),this.a.indexOf(this.Id),this.a.indexOf(this.Hd),this.a.indexOf(this.Kd)];this.j=this.a.indexOf(this.Fe);this.i=this.a.indexOf(this.Ee);this.m= +this.a.indexOf(this.hf)}F(BZ,SM);var CZ=$M(),DZ=aN(),EZ=0;r=BZ.prototype; +r.Od=function(a){var b=a.a;b.i.length||(b.i=Array(this.a.length));b.a&&2==b.a.b&&oO(b);if(!b.a){b.a=new hO(this.v);for(var c=0;c<this.h.length;++c)b.i[this.h[c]]=null;b.ra=0;b.pa=0}if(1==b.a.b)return DZ;for(c=0;c<this.a.length;++c){var d=b.i[c];if(!d&&(d=this.a[c],d!=this.Fd&&d!=this.Id||"success"==b.i[this.j].getState())&&(d!=this.Gd&&d!=this.Jd||"success"==b.i[this.i].getState())&&(d!=this.Hd||"success"==b.i[this.m].getState())&&(d!=this.Kd||"success"==b.i[this.j].getState()&&"success"==b.i[this.i].getState()&& +"success"==b.i[this.m].getState()))return b.i[c]=d.call(this,a),CZ}a=[];for(c=0;c<this.a.length;++c)(d=b.i[c])&&"pending"==d.getState()&&a.push(d);return a.length?dN.apply(null,a):DZ};r.Ub=function(a){for(var b=0;b<this.a.length;++b){var c=a.a.i[b];if(!c||"success"!=c.getState())return!1}return!0}; +r.Qf=function(a){var b=a.a;if(!b.f){var c=a.N.ba().c,d=PB(this.g,c),e=a.data.i;e.length&&TA(d,e);SA(d,a.data.m);c=mN(a.data,c,d);b.f=c;b.jb=this.g.c;a.data.s=c;nN(a.data)}(e=a.b)&&!UM(e.data)&&(c=a.N.ba().c,d=PB(this.g,c),e=e.data.i,e.length&&TA(d,e));b.va||FZ(this,a);return CZ}; +function FZ(a,b){for(var c=b.a.f,d={},e=[],f=0;f<c.a.length;++f){var g=c.a[f];d[g]||(d[g]=!0,e.push(g))}if((d=b.b)&&!UM(d.data)){c=d.a.va;c||(FZ(a,d),c=d.a.va);a={};for(d=0;d<e.length;++d)a[e[d]]=!0;for(d=0;d<c.length;++d)a[c[d]]||e.push(c[d])}b.a.va=e}r.Fe=function(a){return WM(this,a)}; +r.Ee=function(a){var b=a.data;a=a.a.f;var c=b.a;if(Ey(c)){wy(c);b=b.b;var d={};c=Fy(c);c=c.a?c.a.length:0;for(var e=0;e<c;++e){var f=b.a[1][e].ka();f=CK(a,f);if(0<f.o)for(var g=f.c,h=0;23>h;h++)for(var k=0;k<g;k++){var l=vA(f.v,k,h);l&&l.a&&(l=Xs(l,1),d[l]=!0);(l=vA(f.A,k,h))&&l.a&&(l=Xs(l,1),d[l]=!0);(l=vA(f.u,k,h))&&l.a&&(l=Xs(l,1),d[l]=!0)}}a=Object.keys(d)}else a=[];return VM(this,a)}; +r.hf=function(a){var b=a.data.a,c=a.data.j,d=a.a;d.l=0;var e=new FM;if(null!=b.a&&ry(Ly(b))){d.C=[];for(var f=Ly(b).Aa,g=0;g<f.length;g++){var h=eJ(c,b,g);GZ(this,a,h,e);d.C.push(new AZ(h))}}return 0<d.l?e:CZ};r.Ke=function(a){var b=a.a,c=b.a,d=a.a,e=d.c;e||(e=new xZ(this.o,a.data,d.f),a.a.c=e);b=b.c;(0==b.a?0:!b.Pb())||b.Fa(c);(a=a.b&&a.b.a.c)&&(0==a.a||a.Pb())&&a.Fa(c);return CZ};r.Fd=function(a){this.B.b(a);return CZ}; +r.Gd=function(a){var b=a.a,c=a.data;a=c.b;var d=c.a;c=b.f;var e=[],f={};if(Ey(d)){d=Fy(d).a;for(var g=0;g<d.length;g++){var h=a.a[1][g].ka(),k=CK(c,h);h=c.a[h];if(0<k.o&&!f[h]){f[h]=!0;for(var l=k.c,m=0;23>m;m++)for(var n=0;n<l;n++){var p=vA(k.v,n,m);if(p&&p.a){var q=$s(p,1);e.push(new PW(h,n,m,"stamp",q.width,q.height,p.a))}(p=vA(k.A,n,m))&&p.a&&(q=$s(p,1),e.push(new PW(h,n,m,"startcap",q.width,q.height,p.a)));(p=vA(k.u,n,m))&&p.a&&(q=$s(p,1),e.push(new PW(h,n,m,"endcap",q.width,q.height,p.a)))}}}}e.length&& +(b.A=new QW(this.o.b,this.A,e));return CZ};r.Jd=function(a){var b=a.a;2==this.b[b.ra].b(a,this.s)&&b.ra++;return b.ra==this.b.length?(b.ra=0,b.B=++EZ,CZ):null};r.Id=function(a){var b=a.a;if(!b.v.length)return CZ;var c=b.v[b.pa];2==this.l[c.c].b(a,c)&&b.pa++;return b.pa==b.v.length?(b.pa=0,CZ):null};function GZ(a,b,c,d){c&&(c.Qb()&&(a.u&&c.sd(1)?c.Ib(1):c.Ib(3)),c.Db()||c.bc()||(ec(c.Ab(),"load",function(){b.a.l--;0==b.a.l&&HM(d,!0)}),b.a.l++))} +r.Hd=function(a){for(var b=0;b<this.c.length;b++)this.c[b].b(a,this.s);b=a.data;var c=0;null!=b.a.a&&(b=Ly(b.a),c+=b.Aa?b.Aa.length:0);0<c&&(EZ++,a.a.B=EZ);return CZ};r.Kd=function(a){var b=a.a;b.ib=-1;b=b.a;kO(b,this,D(this.Cf,this,a));lO(b);return CZ}; +r.Cf=function(a){a=a.a;a.G=null;a.ja=null;a.I=null;a.ga=null;a.L=null;a.T=[];a.ha=[];a.U=[];a.W=[];a.P=[];a.S=[];a.ya=null;if(a.C)for(var b=0;b<a.C.length;b++)a.C[b].Xb=null;a.c&&0!=a.c.a&&a.c.Sb();a.u&&0!=a.u.a&&a.u.Sb();a.A&&0!=a.A.a&&a.A.Sb();a.o&&0!=a.o.a&&a.o.Sb();a.H&&0!=a.H.a&&a.H.Sb()};function HZ(a,b){if(UM(b.data))return!0;var c=b.a;return c.a&&1==c.a.b?a.Ub(b):!1};function IZ(a,b,c,d,e){$N.call(this,a,b,c,d);this.s=e}F(IZ,$N);IZ.prototype.i=function(a,b,c,d){IZ.R.i.call(this,a,b,c,d);(b=a.b)&&this.s&&a.i&&(a=71.5*Math.sin(ao(SN(this.b))),b.screenY-=a)};IZ.prototype.l=function(a,b){for(var c=0;c<b.c.length;c++)rZ(a.a.c,b.c[c].a,b.f,lK(b))};function JZ(a){return function(b){var c=a.a;b=b.N;for(var d=0;d<c.g.length;d++)if(c.g[d].N.aa()==b.aa()){c.h=!0;break}}};function KZ(a){this.context=a}KZ.prototype.getContext=function(){return this.context};function LZ(a){this.context=a;this.a=this.b=0}F(LZ,KZ);function MZ(a,b,c){a.b=b;a.a=c;a.context.bindFramebuffer(36160,null);a.context.bindRenderbuffer(36161,null);a.context.viewport(0,0,b,c)} +LZ.prototype.bindTexture=function(a){var b=this.context.a.f||null,c=Fp(this.context.b);MZ(this,this.b,this.a);this.context.activeTexture(33984+a);a=this.context.h.createTexture(9729);this.context.bindTexture(3553,this.context.h.a.get(a)||null);this.context.copyTexImage2D(3553,0,6408,0,0,this.b,this.a,0);this.context.a.lc(b);c&&this.context.b.nc(c[0],c[1],c[2],c[3]);return!0};function NZ(a,b,c,d,e,f,g,h,k,l){this.b=e;var m=e.a,n=m.getContext().j;this.j=new yY;var p=new IZ(b,D(this.Mf,this),0,!0,l.Nb);xP.call(this,a,b,d,this,m.h,l,p,n,c);this.ja=new zY(D(this.Wb,this));this.fa=l.s?new tZ(m,f,l.Nb,"arial,sans-serif",l.s,JZ(p)):new qZ(m,f,l.Nb,"arial,sans-serif");this.U=new no(this);Jb(this,this.U);this.U.cb(e,"webglcontextrestored",this.Rf,!1);this.M=new BY(b.a,b,g);a=b.D;this.g=new oq(a.top,a.right,a.bottom,a.left);this.B=g;this.H=l.s;this.D=f;this.Z=h;this.J=17664;this.ra= +l.u;this.W=l.T;this.T=l.G;this.pa=l.ga;this.Y=m;this.S=k;this.ia=l.fa;this.K=this.m=b.g;this.j.O=this.W;this.l=new BZ(m,h,f,this.fa,nY(this.b),oY(this.b),pY(this.b),l);this.ga=new EP(this.l,this.Y.h.b);QP(this.a,D(this.Wb,this));b=D(this.Wb,this);this.B.m=b;this.T||(this.D.l=!1);this.G=1<l.L;this.h=0;this.A=new EY;this.s=new EY}F(NZ,xP);NZ.prototype.X=function(){var a=this.b;a.v--;if(0==a.v){for(var b=0;b<mY.length;b++)if(mY[b].td===a){mY.splice(b,1);break}a.a.$();a.D.$()}}; +var OZ=[[0,0],[.2,.4],[-.2,-.4],[.4,-.2],[-.4,.2]];r=NZ.prototype;r.getContext=function(){return this.Y.getContext()};r.Rf=function(){var a=this.l,b=oY(this.b),c=pY(this.b);a.b=nY(this.b);a.l=b;a.c=c;this.c=new QO;a=this.B;b=this.getContext();a.i=b;a.f=null;a.c=!1;a.g=!0;this.G&&(this.A=new EY,this.s=new EY,this.h=0);a=this.f.a;for(b=0;b<a.length;++b)PZ(this,a[b]);this.Wb()};function PZ(a,b){b.b&&!a.fb(b.b)&&PZ(a,b.b);b.a.a&&oO(b.a);TM(a.l,b)} +r.Vd=function(){return QZ(this)||ZB(this.D)||AP(this)||this.c.a?!1:!0};function QZ(a){return AP(a)?!0:a.i<a.I||!a.b.h.b.b}function RZ(a){var b=a.f.a;return a.G&&a.h<OZ.length&&0<b.length&&a.c.c}r.Qd=function(){var a=this.getContext();return!a||a.isContextLost()?!1:NZ.R.Qd.call(this)}; +r.vc=function(){NZ.R.vc.call(this);var a=PB(this.Z,this.a.ba().c),b=this.D;b.a!=a&&(b.b=b.a,b.b&&WA(b.b),b.a=a,VA(b.a,b.s,b),b.c++,b.l&&b.b&&(b.j=E()+167,b.g||(b.g=!0,b.m.Pd(b))));a=this.Z.c;this.j.md=OA(a,23);this.j.G=OA(a,24);a=this.f.a;for(b=0;b<a.length;++b){var c=a[b];bQ(this.V,c);zZ(c.a.c);(c=c.b)&&c.a.c&&(bQ(this.V,c),zZ(c.a.c))}a.length&&this.H&&uZ(this.fa,this.a.a.f>SZ);c=this.getContext();a=this.j;var d=this.a.i;b=this.a.c;a.C=this.pa?AY(this.ja,this.a.a.G):0;a.f=c.c.drawingBufferWidth|| +c.j.a.width;a.c=c.c.drawingBufferHeight||c.j.a.height;a.zoom=this.a.getZoom();a.v=!1;0>d.indexOf(0)&&(a.v=!0);this.W||this.ra&&this.T&&this.a.m||(a.v=!0);a.M=!this.a.h;a.L=!this.a.m;a.D=!this.ia||0>d.indexOf(0);a.K=!this.a.o;a.P=this.a.u;a.S=this.a.v;a.s=gI(d,this.a.c);a.clearColor=hI(d,b);c=this.a.D;a.o.top=c.top;a.o.right=c.right;a.o.bottom=c.bottom;a.o.left=c.left;a.l=this.a.f;a.u=-1<b.indexOf(2);b=this.a.a;a.j=b.c;a.i=b.a;a.T=this.H?this.H.fg():0;a.A=this.m?12>a.zoom:!1;b=this.a.getZoom();a=this.B; +22<b&&(b=22);b!=a.h&&(a.h=b,a.g=!0,a.c=!1)}; +r.cd=function(a){NZ.R.cd.call(this,a);var b=this.b,c=this.B,d=this.getContext(),e=this.a.a,f=this.f.b,g=this.f.a,h=this.j;this.m=this.a.g;if(d&&!d.isContextLost()){var k=this.a.D,l=!1;!this.c.a&&this.c.c&&TZ(this)&&!ZB(this.D)&&DY(this.M,g)&&this.g.top==k.top&&this.g.right==k.right&&this.g.bottom==k.bottom&&this.g.left==k.left&&this.K==this.m&&(l=!0);if(l&&this.G){if(this.h<OZ.length){l=OZ[this.h][0];var m=OZ[this.h][1];h.g=!0;h.h=!1;h.a.x=l;h.a.y=m;h.Va.x=2*l/h.f;h.Va.y=2*m/h.c;FY(this.A,d,h.f,h.c, +!0);this.A.bind(d);UV(d,h,17664);rY(b,f,g,e,c,h);FY(this.s,d,h.f,h.c,!1);this.s.bind(d);l=1/(this.h+1);TV(d,h,3,1,1,2,1);TX(b.C,this.A.b,l);this.h++}h.g=!1;h.h=!0;h.a.x=0;h.a.y=0;h.Va.x=0;h.Va.y=0;MZ(this.S,h.f,h.c);TV(d,h,2,1,1,2,1);TX(b.C,this.s.b,1);UV(d,h,256);rY(b,f,g,e,c,h)}else h.g=!this.c.a,h.h=!this.c.a,h.a.x=0,h.a.y=0,h.Va.x=0,h.Va.y=0,MZ(this.S,h.f,h.c),UV(d,h,this.J),rY(b,f,g,e,c,h),this.h=0,JO(this.v),MO(this.v,f);a&&KO(this.v,a);this.M.capture(g);this.g.top=k.top;this.g.right=k.right; +this.g.bottom=k.bottom;this.g.left=k.left;this.K=this.m;this.ya=b.f;this.c.a||(QZ(this)||RZ(this))&&this.Wb();TV(d,h,3,3,1,1,2)}};r.Td=function(){bO(this.C,this.f.a,this.f.f,!this.a.h,this.i,this.j.A)};function TZ(a){for(var b=a.f.a,c=0;c<b.length;++c){var d=b[c];if(!HZ(a.l,d)||d.b&&(d=d.b.a,!d.a||1!=d.a.b))return!1}return!0}r.Mf=function(a){this.I=Math.max(this.I,a);(QZ(this)||RZ(this))&&this.Wb()};var SZ=2E5/6371010;r=NZ.prototype;r.rd=function(){return TZ(this)&&NZ.R.rd.call(this)}; +r.fb=function(a){return a.b&&!this.fb(a.b)?!1:HZ(this.l,a)};r.ic=function(a,b,c){var d=null;a.b&&!this.fb(a.b)&&(d=this.ic(a.b,b));var e;if((e=c&&TM(this.l,a)?$M():GP(this.ga,a,b))&&d&&"pending"==e.getState()&&"pending"==d.getState()){var f=d;e.wait(function(){JM(e)&&f.cancel()})}return e};r.wd=function(){return this.ga.b};r.Je=function(){return!0};function UZ(){}F(UZ,uQ);UZ.prototype.a=function(a,b,c,d,e,f,g,h,k,l){c=f.oc;a:{var m=b.a;for(var n=Yn(a.la,1,2),p=a.Nb,q=0;q<mY.length;++q){var t=mY[q];if(t.context==m&&t.Nb==p&&t.gc==k&&t.la==n){t.td.v++;m=t.td;break a}}q=new RB(m,k,n);q=new kY(q,p);mY.push({context:m,gc:k,la:n,Nb:p,td:q});m=q}k=new YB(c,k.b);n=new sX(b.a,k);uH(e,a.i);b=new NZ(d,e,h,f,m,k,n,c,l?l:new LZ(b.a),a);b.J=17664;h=this.Xc(a,f,b,d);return new xY(d,e,f,b,h,g,a.b)};function VZ(){}VZ.prototype.a=function(){return new UZ};NG(3,new VZ);function WZ(){Pp.call(this);this.c=[];this.b=[];this.a=[];this.f=[]}F(WZ,Pp);var XZ=[],YZ=!0;WZ.prototype.h=function(a,b){if(this.c[a])if(this.b[a])b(a,this.c[a]);else return this.a[a].push(b),this.a[a].length-1;return-1};WZ.prototype.g=function(a){this.b[a]=!0;var b=this.a[a];this.a[a]=[];if(b)for(var c=0;c<b.length;++c){var d=b[c];d&&d(a,this.c[a])}}; +function oH(a,b){2==b&&!a.b[b]&&a.b[3]&&a.g(b);if(a.c[b]&&!a.b[b]&&!a.f[b]){a.f[b]=!0;if(YZ){var c=XZ[b];void 0===c&&(c=.1>Math.random()?0:Math.floor(Math.random()*Math.random()*2E3),XZ[b]=c)}else c=0;0==c?a.g(b):ho(D(a.g,a,b),c)}}WZ.prototype.X=function(){for(var a=0;a<this.a.length;a++)if(this.a[a])for(var b=0;b<this.a[a].length;b++);this.a=[];this.f=[];this.b=[];this.c=[];WZ.R.X.call(this)};for(OG=new WZ;PG.length;){var ZZ=PG.shift();NG(ZZ.id,ZZ.If)};function $Z(a){this.a=a?new LH:new CH;YZ=!1};function a_(a){this.b=a}a_.prototype.a=function(a,b,c,d,e,f){for(var g=[],h=0;h<this.b.length;h++)g=g.concat(this.b[h].a(a,b,c,d,e,f));return g};function b_(a){this.b=a} +b_.prototype.a=function(a,b,c,d,e,f){for(var g=[],h=0;h<d.length;h++)for(var k=tQ(e,a,b,f).a,l=0;l<k.length;++l){var m=[],n=k[l].a,p=m,q=bC(n);if(q){var t=q.oa,v=q.Yc,u=q.xc;q=q.bd;var w=n.length;if(w){var y=n[0].getZoom();if(0!=y&&0!=this.b){var A=1<<y;t-=this.b;0>t&&(t=A+t);v+=this.b;v-t>=A&&(v=t+A-1);u-=this.b;0>u&&(u=0);q+=this.b;for(q>=A&&(q=A-1);t<=v;++t){var z=t;z>=A&&(z-=A);for(var C=u;C<=q;++C){for(var I=!0,S=0;S<w;++S)if(n[S].b==z&&n[S].a==C){I=!1;break}I&&p.push(new kC(z,C,y))}}}}}0<m.length&& +g.push(new qQ(m,c,d[h],0,3,!1,!0))}return g};function c_(a){this.b=a}function d_(){for(var a=Array(22),b=0;b<a.length;b++)a[b]=Math.max(0,b-2);return new c_(a)} +c_.prototype.a=function(a,b,c,d,e,f){var g=[];a=tQ(e,a,b,f).a;for(b=0;b<a.length;++b){e=[];var h=a[b].a;f=e;var k=bC(h);if(k){var l=h[0].getZoom();h=this.b[l];if(!(0>h||h==l)){var m=l-h,n=k.oa>>m;l=k.Yc>>m;var p=k.xc>>m;k=k.bd>>m;m=1<<h;--n;0>n&&(n=Math.max(0,m+n));l+=1;l-n>=m&&(l=n+m-1);--p;0>p&&(p=0);k+=1;for(k>=m&&(k=m-1);n<=l;++n){var q=n;q>=m&&(q-=m);for(var t=p;t<=k;++t)f.push(new kC(q,t,h))}}}if(0<e.length)for(f=0;f<d.length;f++)g.push(new qQ(e,c,d[f],0,3,!1,!0))}return g};function e_(a,b,c,d){this.a=a;this.h=b;this.l=c;this.c=this.f=!1;this.g=null;0<d&&(a=[new b_(d)],a.push(d_()),this.g=new a_(a));this.b=null;QP(this.a,D(this.j,this))}e_.prototype.j=function(){this.f||this.c||(this.f=!0,this.l.Te(this))};function Mr(a){if(!a.c){var b=tU(a.h,a.a.a,a.a.f,a.a.ba(),a.a.c,a.a.g);a.b&&(a.b.cancel(),a.b=null);bN(b,a.i,a)}a.f=!1} +e_.prototype.i=function(){if(this.g){var a=this.h,b=this.g.a(this.a.a,this.a.f,this.a.ba(),this.a.c,a.g,this.a.g);this.b=uU(a,b,!1)}a=this.h;1!=a.b&&(a.b=!0,a.c&&vU(a,a.c))};function f_(a){this.a=new pB;xB(this.a,!0);for(var b=0;b<arguments.length;b++){var c=arguments[b];c&&(c=c.replace(/^\?/,""),this.a.zf(new pB(c)))}}f_.prototype.has=function(a){return DB(this.a,a)};f_.prototype.get=function(a,b){return this.a.get(a,b)};function g_(a,b){a=a.a.get(b);return""==a||"true"==a||"yes"==a}f_.prototype.numeric=function(a,b){a=this.a.get(a);return"undefined"==typeof a?b||0:parseFloat(a)};function h_(){this.b=new f_(x.location.search,x.testConfig);this.G=this.b.get("testmode","normal");this.g=[];this.I=0;this.C=this.u=!1;this.D=void 0;this.l=0;this.c=null;this.H=new bP;this.s=[];this.o=[];this.j=[];this.m=!1;this.v=this.i=this.B=0;this.h=new $Z(g_(this.b,"nobudget"));var a=this.b.get("viewport"),b=new tC,c=KD[a];if(!B(c))throw Error("Unknown viewport: "+a);var d;if(d=c)uC||wC(),d=!qs.a(c,b.data,uC);if(d)throw Error("Failed to parse viewport:"+a);this.a=new pC(b.data[0]);a=this.b;c= +this.a;d=new OF;d.u=["/vt"];d.v=["/kh?v=0"];d.f="en";d.c="";d.o=g_(a,"nodraw");d.i=g_(a,"canvas")?2:1;var e=VE(ze(c,13,"Default"));d.m=lC(e);d.s=nC(e);d.b=g_(a,"useDiffTiles");d.b&&(e=VE("Default"),d.h=nC(e),d.a=lC(e));a.has("overridePixelRatio")&&(d.g=a.numeric("overridePixelRatio"));d.l=X(c,0,512);d.j=X(c,1,512);this.J=d;a=this.b;c=new LF;c.I=!g_(a,"noLabels");c.u=!g_(a,"noGrids");c.J=1;c.L=0;"false"==a.get("requestDxtTextures","")?c.h=!1:c.h=!0;c.g=g_(a,"rasterizeNonInteractiveFeatures");c.f=100; +c.S=!1;this.A=c;this.A.o=D(this.h.a.j,this.h.a);this.f=this.pb=null;b=new xC(b);for(a=b.a.shift();a;)i_(this,a),a=b.a.shift();this.b.has("title")&&(document.title=this.b.get("title"))}var j_={Uf:"normal",Vf:"static",Wf:"stress"};function i_(a,b){var c=a.H;a.g.push(function(a){vH(a,c);c.lat=X(b,2,47.651318);c.lng=X(b,3,-122.35305);c.zoom=b.getZoom();c.ta=X(b,7);c.rotation=X(b,6);wH(a,c)});xe(b,31)&&a.jf(X(b,31))}r=h_.prototype; +r.jf=function(a){this.g.push(D(function(){this.c=setTimeout(D(function(){this.c=null;this.Ne()},this),a)},this))};r.Sf=function(){var a=D(this.Of,this);"undefined"!=window&&(a=mF(new jF("/error",void 0,void 0),a)||a);if(g_(this.b,"workers")){var b=null;b=g_(this.b,"debugjs")?new Worker("worker-bundle.js"):new Worker("worker.js");var c=this,d=function(e){"dataset_loaded"==e.data&&(b.removeEventListener("message",d),c.A.b=new CF([b]),a())};b.addEventListener("message",d)}else a()}; +r.Of=function(){var a=go("div");a.id="map_div";a.style.display="inline-block";document.body.appendChild(a);a=this.pb=new lH(this.J,this.h,a);var b=D(this.Af,this);var c=a.b;var d=a.h,e=this.A;B(e)||(e=new LF,e.m=!0);if(1==d||2==d){var f=2==d;f&&null==e.g&&(e.g=!0);d=c.b;e.g&&(d=!1);e.c=f?2:1;f=c.u||["//www.google.com/maps/vt"];var g=c.v||["//khms0.google.com/kh?v=0","//khms1.google.com/kh?v=0","//khms2.google.com/kh?v=0","//khms3.google.com/kh?v=0"];e.j=f;e.v=f;e.K=f;e.O=PF(f,"/stream");e.U=g;e.ia= +PF(f,"?lyrs=t");e.B=d;e.la=c.g;e.a=c.A;e.M=c.A;e.V=c.C}c=e;if(c.m){a.f=new VG;c.H=a.f;c.Y=a.f;e=new On;e.data[0]=0;e.data[1]="m";e.data[2]=1E6*c.f;d=a.f;f=c.f;1E6<=f&&(f=(f-f%1E6)/1E6);f=1E6*f+999999;g=Ds(e);var h=d.a[g];h||(h=new XG(xe(e,2)?X(e,2):null,new UG(d.f,d.c,f)),d.a[g]=h,d.b[e.wa()]=g)}null==c.h&&a.j.a&&a.j.a.Zc&&a.j.a.Zc()&&(c.h=!0);nH(a,c,D(a.Bf,a,b))}; +r.Af=function(){var a=mH(this.pb),b=a.b;this.f=new e_(b,a.i,this.h.a,g_(this.b,"noprefetch")?0:1);var c=this.pb.g;c.a=null;uo(c);this.f&&(this.f.c=!0);c=vH(b,this.H);c.lat=X(this.a,2,47.651318);c.lng=X(this.a,3,-122.35305);c.zoom=this.a.getZoom();c.a=X(this.a,5);c.rotation=X(this.a,6);c.ta=X(this.a,7);c.b=X(this.a,10,13.1);wH(b,c);c=X(this.a,8,-212);var d=X(this.a,9,40);if(b.u!=c||b.v!=d)b.u=c,b.v=d,tH(b);c=(0==Fe(this.a,11)?void 0:Ce(this.a,11))||[0];Xa(b.c,c)||(b.c=c.slice(),tH(b));0<Fe(this.a, +12)&&(c=Ce(this.a,12),Xa(b.i,c)||(b.i=c.slice(),tH(b)));a=a.g();"stress"!=this.G&&(dc(a,"FrameComplete",this.lf,!1,this),dc(a,"FrameStart",this.nf,!1,this));dc(a,"FrameComplete",this.Ne,!1,this);a=g_(this.b,"wait")?D(this.xf,this):D(this.Rd,this);JD(a)};r.xf=function(){window?window.startTest=D(this.Rd,this):this.Rd()}; +r.Rd=function(){this.u&&(this.C?(window.wtf.trace.prepare({"wtf.trace.mode":"snapshotting"}),window.wtf.trace.start()):window.wtf.trace.reset(),window.wtf.trace.mark("analysisStart"));var a=this.pb,b=a.g;b.a=a.a;uo(b);this.f&&(this.f.c=!1);this.I=E();setTimeout(D(this.yc,this),0)};r.Ne=function(){this.m&&(this.m=!1,this.yc())}; +r.yc=function(){var a=mH(this.pb);if(null==this.c||0!=a.a.f.a.length&&a.a.Vd())if(0<this.g.length){var b=this.g.shift();this.l=0;this.c&&(clearTimeout(this.c),this.c=null);b(a.b);this.l?setTimeout(D(this.yc,this),this.l):a.a.Vd()?this.yc():this.m=!0}else ur(D(this.Nf,this));else setTimeout(D(this.yc,this),0)};r.vf=function(a,b){this.C=a;this.u=!0;this.D=b}; +r.Nf=function(){var a=E()-this.I-0;this.u&&window.wtf.trace.snapshot(this.D);var b=[];b.push("total="+a);b.push("missed_frames="+60*this.i/1E3);"stress"!=this.G&&(a=CP(mH(this.pb).f().m()),b.push("average_prep_time="+a.toFixed(1)),b.push("num_frames="+this.s.length),b.push("incomplete_frames="+this.j.length),b.push("total_renderables="+this.v),a=bo.apply(null,this.j),b.push("missing_renderables="+a),a=co.apply(null,this.o)/1048576,b.push("average_gpu_memory_mb="+a),a={},a.render=k_(this.s,33),a.gpu_memory= +k_(this.o,0),a.gpu_memory.fd=void 0,gb(a,function(a,d){b.push(d+"="+[a.min,a.pc,a.dc[0],a.dc[1],a.dc[2],a.max].join());"number"==typeof a.fd&&b.push("slow"+d+"="+a.fd)}));x.environment&&(a=x.environment.Variables)&&a.cl&&b.push("cl="+a.cl);a="/metrics?"+b.join("&");x.testMetrics=b.join("&");qD(a,D(function(){x.testDone=!0},this))};r.lf=function(a){this.s.push(a.h-a.startTime);this.v+=a.g;this.o.push(a.f);0<a.c&&this.j.push(a.c)}; +r.nf=function(a){a=a.startTime;this.B&&(this.i+=a-this.B-1E3/60);this.B=a};function k_(a,b){var c={};c.min=a[0];c.max=c.min;c.pc=c.min;for(var d=c.fd=0;d<a.length;++d){var e=a[d];c.pc+=e;e<c.min&&(c.min=e);e>c.max&&(c.max=e);e>b&&c.fd++}c.pc/=a.length;a.sort(Za);c.dc=[];c.dc[0]=a[Math.floor(.5*a.length)];c.dc[1]=a[Math.floor(.9*a.length)];c.dc[2]=a[Math.floor(.995*a.length)];return c}window.getMetrics=function(){return x.testMetrics||!1};Ia("Tracker",h_);h_.TEST_MODE=j_;j_.NORMAL="normal"; +j_.STATIC="static";j_.STRESS="stress";h_.prototype.waitForRender=h_.prototype.jf;h_.prototype.run=h_.prototype.Sf;h_.prototype.enableTracing=h_.prototype.vf;}).call(this);
diff --git a/tools/perf/page_sets/maps_perf_test/worker.js b/tools/perf/page_sets/maps_perf_test/worker.js new file mode 100644 index 0000000..0eaacd2 --- /dev/null +++ b/tools/perf/page_sets/maps_perf_test/worker.js
@@ -0,0 +1,294 @@ +(function(){'use strict';var k,aa=aa||{},l=this;function m(a){return void 0!==a}function ba(a){return"string"==typeof a}function ca(a,b){a=a.split(".");var c=l;a[0]in c||!c.execScript||c.execScript("var "+a[0]);for(var d;a.length&&(d=a.shift());)!a.length&&m(b)?c[d]=b:c[d]&&c[d]!==Object.prototype[d]?c=c[d]:c=c[d]={}}function da(){} +function ea(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array";if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("call"))return"function"}else return"null"; +else if("function"==b&&"undefined"==typeof a.call)return"object";return b}function fa(a){var b=typeof a;return"object"==b&&null!=a||"function"==b}function ha(a,b,c){return a.call.apply(a.bind,arguments)}function ia(a,b,c){if(!a)throw Error();if(2<arguments.length){var d=Array.prototype.slice.call(arguments,2);return function(){var c=Array.prototype.slice.call(arguments);Array.prototype.unshift.apply(c,d);return a.apply(b,c)}}return function(){return a.apply(b,arguments)}} +function n(a,b,c){Function.prototype.bind&&-1!=Function.prototype.bind.toString().indexOf("native code")?n=ha:n=ia;return n.apply(null,arguments)}var ja=Date.now||function(){return+new Date};function ka(a,b){function c(){}c.prototype=b.prototype;a.Qa=b.prototype;a.prototype=new c;a.prototype.constructor=a;a.eb=function(a,c,f){for(var d=Array(arguments.length-2),e=2;e<arguments.length;e++)d[e-2]=arguments[e];return b.prototype[c].apply(a,d)}};function la(a,b,c){this.c=a;this.g=b;this.a=null;this.f=c;this.b=-1}la.prototype.abort=function(){return this.a?this.a():!1};la.prototype.postMessage=function(a,b,c){var d={};d.id=this.c;d.payload=a;d.complete=b;d.received=this.b;this.g.postMessage(d,c);b&&this.f(this.c)};var ma=Array.prototype.indexOf?function(a,b){return Array.prototype.indexOf.call(a,b,void 0)}:function(a,b){if(ba(a))return ba(b)&&1==b.length?a.indexOf(b,0):-1;for(var c=0;c<a.length;c++)if(c in a&&a[c]===b)return c;return-1};function na(a){a:{var b=oa;for(var c=a.length,d=ba(a)?a.split(""):a,e=0;e<c;e++)if(e in d&&b.call(void 0,d[e],e,a)){b=e;break a}b=-1}return 0>b?null:ba(a)?a.charAt(b):a[b]} +function pa(a,b,c){return 2>=arguments.length?Array.prototype.slice.call(a,b):Array.prototype.slice.call(a,b,c)};var qa=String.prototype.trim?function(a){return a.trim()}:function(a){return/^[\s\xa0]*([\s\S]*?)[\s\xa0]*$/.exec(a)[1]};function ra(a,b){return a<b?-1:a>b?1:0};var sa;a:{var ta=l.navigator;if(ta){var ua=ta.userAgent;if(ua){sa=ua;break a}}sa=""}function p(a){return-1!=sa.indexOf(a)};var va="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" ");function wa(a,b){for(var c,d,e=1;e<arguments.length;e++){d=arguments[e];for(c in d)a[c]=d[c];for(var f=0;f<va.length;f++)c=va[f],Object.prototype.hasOwnProperty.call(d,c)&&(a[c]=d[c])}};function xa(){return(p("Chrome")||p("CriOS"))&&!p("Edge")};function ya(){return p("iPhone")&&!p("iPod")&&!p("iPad")};function za(a){za[" "](a);return a}za[" "]=da;function Ba(a,b){var c=Ca;return Object.prototype.hasOwnProperty.call(c,a)?c[a]:c[a]=b(a)};var Da=p("Opera"),Ea=p("Trident")||p("MSIE"),Fa=p("Edge"),Ga=p("Gecko")&&!(-1!=sa.toLowerCase().indexOf("webkit")&&!p("Edge"))&&!(p("Trident")||p("MSIE"))&&!p("Edge"),Ha=-1!=sa.toLowerCase().indexOf("webkit")&&!p("Edge");function Ia(){var a=l.document;return a?a.documentMode:void 0}var Ja; +a:{var Ka="",La=function(){var a=sa;if(Ga)return/rv:([^\);]+)(\)|;)/.exec(a);if(Fa)return/Edge\/([\d\.]+)/.exec(a);if(Ea)return/\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(a);if(Ha)return/WebKit\/(\S+)/.exec(a);if(Da)return/(?:Version)[ \/]?(\S+)/.exec(a)}();La&&(Ka=La?La[1]:"");if(Ea){var Ma=Ia();if(null!=Ma&&Ma>parseFloat(Ka)){Ja=String(Ma);break a}}Ja=Ka}var Na=Ja,Ca={}; +function Oa(a){return Ba(a,function(){for(var b=0,c=qa(String(Na)).split("."),d=qa(String(a)).split("."),e=Math.max(c.length,d.length),f=0;0==b&&f<e;f++){var g=c[f]||"",h=d[f]||"";do{g=/(\d*)(\D*)(.*)/.exec(g)||["","","",""];h=/(\d*)(\D*)(.*)/.exec(h)||["","","",""];if(0==g[0].length&&0==h[0].length)break;b=ra(0==g[1].length?0:parseInt(g[1],10),0==h[1].length?0:parseInt(h[1],10))||ra(0==g[2].length,0==h[2].length)||ra(g[2],h[2]);g=g[3];h=h[3]}while(0==b)}return 0<=b})}var Pa;var Qa=l.document; +Pa=Qa&&Ea?Ia()||("CSS1Compat"==Qa.compatMode?parseInt(Na,10):5):void 0;function Ra(){this.f=this.f;this.j=this.j}Ra.prototype.f=!1;Ra.prototype.h=function(){this.f||(this.f=!0,this.Ga())};Ra.prototype.Ga=function(){if(this.j)for(;this.j.length;)this.j.shift()()};var Sa;(Sa=!Ea)||(Sa=9<=Number(Pa));var Ta=Sa,Ua=Ea&&!Oa("9"),Va=function(){if(!l.addEventListener||!Object.defineProperty)return!1;var a=!1,b=Object.defineProperty({},"passive",{get:function(){a=!0}});l.addEventListener("test",da,b);l.removeEventListener("test",da,b);return a}();function Wa(a,b){this.type=a;this.a=this.target=b;this.Ua=!0}Wa.prototype.b=function(){this.Ua=!1};function Xa(a,b){Wa.call(this,a?a.type:"");this.relatedTarget=this.a=this.target=null;this.button=this.screenY=this.screenX=this.clientY=this.clientX=0;this.key="";this.metaKey=this.shiftKey=this.altKey=this.ctrlKey=!1;this.pointerId=0;this.pointerType="";this.c=null;if(a){var c=this.type=a.type,d=a.changedTouches?a.changedTouches[0]:null;this.target=a.target||a.srcElement;this.a=b;if(b=a.relatedTarget){if(Ga){a:{try{za(b.nodeName);var e=!0;break a}catch(f){}e=!1}e||(b=null)}}else"mouseover"==c?b= +a.fromElement:"mouseout"==c&&(b=a.toElement);this.relatedTarget=b;null===d?(this.clientX=void 0!==a.clientX?a.clientX:a.pageX,this.clientY=void 0!==a.clientY?a.clientY:a.pageY,this.screenX=a.screenX||0,this.screenY=a.screenY||0):(this.clientX=void 0!==d.clientX?d.clientX:d.pageX,this.clientY=void 0!==d.clientY?d.clientY:d.pageY,this.screenX=d.screenX||0,this.screenY=d.screenY||0);this.button=a.button;this.key=a.key||"";this.ctrlKey=a.ctrlKey;this.altKey=a.altKey;this.shiftKey=a.shiftKey;this.metaKey= +a.metaKey;this.pointerId=a.pointerId||0;this.pointerType=ba(a.pointerType)?a.pointerType:Ya[a.pointerType]||"";this.c=a;a.defaultPrevented&&this.b()}}ka(Xa,Wa);var Ya={2:"touch",3:"pen",4:"mouse"};Xa.prototype.b=function(){Xa.Qa.b.call(this);var a=this.c;if(a.preventDefault)a.preventDefault();else if(a.returnValue=!1,Ua)try{if(a.ctrlKey||112<=a.keyCode&&123>=a.keyCode)a.keyCode=-1}catch(b){}};var Za="closure_listenable_"+(1E6*Math.random()|0);function $a(a){return!(!a||!a[Za])}var ab=0;function bb(a,b,c,d,e){this.listener=a;this.a=null;this.src=b;this.type=c;this.capture=!!d;this.Ja=e;this.key=++ab;this.xa=this.Ha=!1}function cb(a){a.xa=!0;a.listener=null;a.a=null;a.src=null;a.Ja=null};function db(a){this.src=a;this.a={};this.b=0}db.prototype.add=function(a,b,c,d,e){var f=a.toString();a=this.a[f];a||(a=this.a[f]=[],this.b++);var g=eb(a,b,d,e);-1<g?(b=a[g],c||(b.Ha=!1)):(b=new bb(b,this.src,f,!!d,e),b.Ha=c,a.push(b));return b};function fb(a,b){var c=b.type;if(!(c in a.a))return!1;var d=a.a[c],e=ma(d,b),f;(f=0<=e)&&Array.prototype.splice.call(d,e,1);f&&(cb(b),0==a.a[c].length&&(delete a.a[c],a.b--));return f} +function gb(a){var b=0,c;for(c in a.a){for(var d=a.a[c],e=0;e<d.length;e++)++b,cb(d[e]);delete a.a[c];a.b--}}function eb(a,b,c,d){for(var e=0;e<a.length;++e){var f=a[e];if(!f.xa&&f.listener==b&&f.capture==!!c&&f.Ja==d)return e}return-1};var hb="closure_lm_"+(1E6*Math.random()|0),ib={},jb=0;function kb(a,b,c,d,e){if(d&&d.once)lb(a,b,c,d,e);else if("array"==ea(b))for(var f=0;f<b.length;f++)kb(a,b[f],c,d,e);else c=mb(c),$a(a)?nb(a,b,c,fa(d)?!!d.capture:!!d,e):ob(a,b,c,!1,d,e)} +function ob(a,b,c,d,e,f){if(!b)throw Error("Invalid event type");var g=fa(e)?!!e.capture:!!e,h=pb(a);h||(a[hb]=h=new db(a));c=h.add(b,c,d,g,f);if(!c.a){d=qb();c.a=d;d.src=a;d.listener=c;if(a.addEventListener)Va||(e=g),void 0===e&&(e=!1),a.addEventListener(b.toString(),d,e);else if(a.attachEvent)a.attachEvent(rb(b.toString()),d);else if(a.addListener&&a.removeListener)a.addListener(d);else throw Error("addEventListener and attachEvent are unavailable.");jb++}} +function qb(){var a=sb,b=Ta?function(c){return a.call(b.src,b.listener,c)}:function(c){c=a.call(b.src,b.listener,c);if(!c)return c};return b}function lb(a,b,c,d,e){if("array"==ea(b))for(var f=0;f<b.length;f++)lb(a,b[f],c,d,e);else c=mb(c),$a(a)?a.U.add(String(b),c,!0,fa(d)?!!d.capture:!!d,e):ob(a,b,c,!0,d,e)} +function tb(a,b,c,d,e){if("array"==ea(b))for(var f=0;f<b.length;f++)tb(a,b[f],c,d,e);else(d=fa(d)?!!d.capture:!!d,c=mb(c),$a(a))?(a=a.U,b=String(b).toString(),b in a.a&&(f=a.a[b],c=eb(f,c,d,e),-1<c&&(cb(f[c]),Array.prototype.splice.call(f,c,1),0==f.length&&(delete a.a[b],a.b--)))):a&&(a=pb(a))&&(b=a.a[b.toString()],a=-1,b&&(a=eb(b,c,d,e)),(c=-1<a?b[a]:null)&&ub(c))} +function ub(a){if("number"==typeof a||!a||a.xa)return!1;var b=a.src;if($a(b))return fb(b.U,a);var c=a.type,d=a.a;b.removeEventListener?b.removeEventListener(c,d,a.capture):b.detachEvent?b.detachEvent(rb(c),d):b.addListener&&b.removeListener&&b.removeListener(d);jb--;(c=pb(b))?(fb(c,a),0==c.b&&(c.src=null,b[hb]=null)):cb(a);return!0}function rb(a){return a in ib?ib[a]:ib[a]="on"+a} +function vb(a,b,c,d){var e=!0;if(a=pb(a))if(b=a.a[b.toString()])for(b=b.concat(),a=0;a<b.length;a++){var f=b[a];f&&f.capture==c&&!f.xa&&(f=wb(f,d),e=e&&!1!==f)}return e}function wb(a,b){var c=a.listener,d=a.Ja||a.src;a.Ha&&ub(a);return c.call(d,b)} +function sb(a,b){if(a.xa)return!0;if(!Ta){if(!b)a:{b=["window","event"];for(var c=l,d=0;d<b.length;d++)if(c=c[b[d]],null==c){b=null;break a}b=c}d=b;b=new Xa(d,this);c=!0;if(!(0>d.keyCode||void 0!=d.returnValue)){a:{var e=!1;if(0==d.keyCode)try{d.keyCode=-1;break a}catch(g){e=!0}if(e||void 0==d.returnValue)d.returnValue=!0}d=[];for(e=b.a;e;e=e.parentNode)d.push(e);a=a.type;for(e=d.length-1;0<=e;e--){b.a=d[e];var f=vb(d[e],a,!0,b);c=c&&f}for(e=0;e<d.length;e++)b.a=d[e],f=vb(d[e],a,!1,b),c=c&&f}return c}return wb(a, +new Xa(b,this))}function pb(a){a=a[hb];return a instanceof db?a:null}var xb="__closure_events_fn_"+(1E9*Math.random()>>>0);function mb(a){if("function"==ea(a))return a;a[xb]||(a[xb]=function(b){return a.handleEvent(b)});return a[xb]};function q(){Ra.call(this);this.U=new db(this);this.D=this;this.B=null}ka(q,Ra);q.prototype[Za]=!0;q.prototype.addEventListener=function(a,b,c,d){kb(this,a,b,c,d)};q.prototype.removeEventListener=function(a,b,c,d){tb(this,a,b,c,d)}; +q.prototype.dispatchEvent=function(a){var b,c=this.B;if(c)for(b=[];c;c=c.B)b.push(c);c=this.D;var d=a.type||a;if(ba(a))a=new Wa(a,c);else if(a instanceof Wa)a.target=a.target||c;else{var e=a;a=new Wa(d,c);wa(a,e)}e=!0;if(b)for(var f=b.length-1;0<=f;f--){var g=a.a=b[f];e=yb(g,d,!0,a)&&e}g=a.a=c;e=yb(g,d,!0,a)&&e;e=yb(g,d,!1,a)&&e;if(b)for(f=0;f<b.length;f++)g=a.a=b[f],e=yb(g,d,!1,a)&&e;return e};q.prototype.Ga=function(){q.Qa.Ga.call(this);this.U&&gb(this.U);this.B=null}; +function nb(a,b,c,d,e){a.U.add(String(b),c,!1,d,e)}function yb(a,b,c,d){b=a.U.a[String(b)];if(!b)return!0;b=b.concat();for(var e=!0,f=0;f<b.length;++f){var g=b[f];if(g&&!g.xa&&g.capture==c){var h=g.listener,r=g.Ja||g.src;g.Ha&&fb(a.U,g);e=!1!==h.call(r,d)&&e}}return e&&0!=d.Ua};var zb="StopIteration"in l?l.StopIteration:{message:"StopIteration",stack:""};function Ab(){}Ab.prototype.next=function(){throw zb;};Ab.prototype.Xa=function(){return this};function Bb(a){switch(a){case 200:case 201:case 202:case 204:case 206:case 304:case 1223:return!0;default:return!1}};function Cb(){}Cb.prototype.a=null;function Db(a){var b;(b=a.a)||(b={},Eb(a)&&(b[0]=!0,b[1]=!0),b=a.a=b);return b};var Fb;function Gb(){}ka(Gb,Cb);function Hb(a){return(a=Eb(a))?new ActiveXObject(a):new XMLHttpRequest}function Eb(a){if(!a.b&&"undefined"==typeof XMLHttpRequest&&"undefined"!=typeof ActiveXObject){for(var b=["MSXML2.XMLHTTP.6.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","Microsoft.XMLHTTP"],c=0;c<b.length;c++){var d=b[c];try{return new ActiveXObject(d),a.b=d}catch(e){}}throw Error("Could not create ActiveXObject. ActiveX might be disabled, or MSXML might not be installed");}return a.b}Fb=new Gb;function Ib(a,b){this.b={};this.a=[];this.f=this.c=0;var c=arguments.length;if(1<c){if(c%2)throw Error("Uneven number of arguments");for(var d=0;d<c;d+=2)this.set(arguments[d],arguments[d+1])}else if(a)if(a instanceof Ib)for(c=a.La(),d=0;d<c.length;d++)this.set(c[d],a.get(c[d]));else for(d in a)this.set(d,a[d])}k=Ib.prototype;k.La=function(){Jb(this);return this.a.concat()};k.clear=function(){this.b={};this.f=this.c=this.a.length=0}; +function Jb(a){if(a.c!=a.a.length){for(var b=0,c=0;b<a.a.length;){var d=a.a[b];Object.prototype.hasOwnProperty.call(a.b,d)&&(a.a[c++]=d);b++}a.a.length=c}if(a.c!=a.a.length){var e={};for(c=b=0;b<a.a.length;)d=a.a[b],Object.prototype.hasOwnProperty.call(e,d)||(a.a[c++]=d,e[d]=1),b++;a.a.length=c}}k.get=function(a,b){return Object.prototype.hasOwnProperty.call(this.b,a)?this.b[a]:b};k.set=function(a,b){Object.prototype.hasOwnProperty.call(this.b,a)||(this.c++,this.a.push(a),this.f++);this.b[a]=b}; +k.forEach=function(a,b){for(var c=this.La(),d=0;d<c.length;d++){var e=c[d],f=this.get(e);a.call(b,f,e,this)}};k.Xa=function(a){Jb(this);var b=0,c=this.f,d=this,e=new Ab;e.next=function(){if(c!=d.f)throw Error("The map has changed since the iterator was created");if(b>=d.a.length)throw zb;var e=d.a[b++];return a?e:d.b[e]};return e};function Kb(a,b,c){if("function"==ea(a))c&&(a=n(a,c));else if(a&&"function"==typeof a.handleEvent)a=n(a.handleEvent,a);else throw Error("Invalid listener argument");return 2147483647<Number(b)?-1:l.setTimeout(a,b||0)};var Lb=/^(?:([^:/?#.]+):)?(?:\/\/(?:([^/?#]*)@)?([^/#?]*?)(?::([0-9]+))?(?=[/#?]|$))?([^?#]+)?(?:\?([^#]*))?(?:#([\s\S]*))?$/;function Mb(a){q.call(this);this.headers=new Ib;this.u=a||null;this.b=!1;this.s=this.a=null;this.A="";this.c=this.w=this.i=this.v=!1;this.m=0;this.l=null;this.g="";this.C=this.o=!1}ka(Mb,q);var Nb=/^https?$/i,Ob=["POST","PUT"]; +function Pb(a,b,c,d){if(a.a)throw Error("[goog.net.XhrIo] Object is active with another request="+a.A+"; newUri="+b);c=c?c.toUpperCase():"GET";a.A=b;a.v=!1;a.b=!0;a.a=a.u?Hb(a.u):Hb(Fb);a.s=a.u?Db(a.u):Db(Fb);a.a.onreadystatechange=n(a.Ta,a);try{a.w=!0,a.a.open(c,String(b),!0),a.w=!1}catch(g){Qb(a);return}b=d||"";d=new Ib(a.headers);var e=na(d.La()),f=l.FormData&&b instanceof l.FormData;!(0<=ma(Ob,c))||e||f||d.set("Content-Type","application/x-www-form-urlencoded;charset=utf-8");d.forEach(function(a, +b){this.a.setRequestHeader(b,a)},a);a.g&&(a.a.responseType=a.g);"withCredentials"in a.a&&a.a.withCredentials!==a.o&&(a.a.withCredentials=a.o);try{Rb(a),0<a.m&&(a.C=Sb(a.a),a.C?(a.a.timeout=a.m,a.a.ontimeout=n(a.Wa,a)):a.l=Kb(a.Wa,a.m,a)),a.i=!0,a.a.send(b),a.i=!1}catch(g){Qb(a)}}function Sb(a){return Ea&&Oa(9)&&"number"==typeof a.timeout&&m(a.ontimeout)}function oa(a){return"content-type"==a.toLowerCase()}k=Mb.prototype; +k.Wa=function(){"undefined"!=typeof aa&&this.a&&(this.dispatchEvent("timeout"),this.abort(8))};function Qb(a){a.b=!1;a.a&&(a.c=!0,a.a.abort(),a.c=!1);Tb(a);Ub(a)}function Tb(a){a.v||(a.v=!0,a.dispatchEvent("complete"),a.dispatchEvent("error"))}k.abort=function(){this.a&&this.b&&(this.b=!1,this.c=!0,this.a.abort(),this.c=!1,this.dispatchEvent("complete"),this.dispatchEvent("abort"),Ub(this))};k.Ga=function(){this.a&&(this.b&&(this.b=!1,this.c=!0,this.a.abort(),this.c=!1),Ub(this,!0));Mb.Qa.Ga.call(this)}; +k.Ta=function(){this.f||(this.w||this.i||this.c?Vb(this):this.Za())};k.Za=function(){Vb(this)};function Vb(a){if(a.b&&"undefined"!=typeof aa&&(!a.s[1]||4!=Wb(a)||2!=Xb(a)))if(a.i&&4==Wb(a))Kb(a.Ta,0,a);else if(a.dispatchEvent("readystatechange"),4==Wb(a)){a.b=!1;try{Yb(a)?(a.dispatchEvent("complete"),a.dispatchEvent("success")):Tb(a)}finally{Ub(a)}}}function Ub(a,b){if(a.a){Rb(a);var c=a.a,d=a.s[0]?da:null;a.a=null;a.s=null;b||a.dispatchEvent("ready");try{c.onreadystatechange=d}catch(e){}}} +function Rb(a){a.a&&a.C&&(a.a.ontimeout=null);a.l&&(l.clearTimeout(a.l),a.l=null)}function Yb(a){var b=Xb(a),c;if(!(c=Bb(b))){if(b=0===b)a=String(a.A).match(Lb)[1]||null,!a&&l.self&&l.self.location&&(a=l.self.location.protocol,a=a.substr(0,a.length-1)),b=!Nb.test(a?a.toLowerCase():"");c=b}return c}function Wb(a){return a.a?a.a.readyState:0}function Xb(a){try{return 2<Wb(a)?a.a.status:-1}catch(b){return-1}}function Zb(a){try{return a.a?a.a.responseText:""}catch(b){return""}} +k.Ia=function(){try{if(!this.a)return null;if("response"in this.a)return this.a.response;switch(this.g){case "":case "text":return this.a.responseText;case "arraybuffer":if("mozResponseArrayBuffer"in this.a)return this.a.mozResponseArrayBuffer}return null}catch(a){return null}};function $b(){this.a=0;this.c=this.b=null}function ac(a,b){a.b=b;a.c=null}$b.prototype.cancel=function(){if(3==this.a)return!1;var a=!1;this.b&&(a=this.b.call(this.c))&&(this.a=3);return a};$b.prototype.start=function(){if(0!=this.a)throw Error("Trying to reuse an Rpc object. Status is not INACTIVE");this.a=1};function bc(a,b){if(0==b)throw Error("Trying to set the Rpc status to INACTIVE.");a.a=b};function cc(a,b,c,d){this.data=a;this.width=b;this.height=c;this.a=d||1};function dc(){this.a=this.c=this.f=this.h=this.g=null;this.b=0}function ec(){this.g=this.f=this.i=this.h=this.a=this.c=this.b=this.status=null}function fc(a){if(!a)return null;var b={};b.data=a.data;b.width=a.width;b.height=a.height;b.format=a.a;return b}function gc(){this.a=this.b=0};function hc(){this.b=[];this.a=new gc}function ic(a,b,c){a=new jc(a,b,c);kc.b.push(a);return n(a.g,a)}function lc(a,b,c){var d=a.b;if(!d.length)return!1;for(var e=0;e<d.length;++e){var f=d[e];if(f.h==b){d.splice(e,1);b=f;for(d=0;d<b.a.length;++d)e=b.a[d],c(e.response,e.complete,e.cb);b.a.length=0;b.b=c;a.a.b++;return!0}}for(e=0;e<d.length;++e)f=d[e],f.abort();d.length=0;a.a.a++;return!1}function jc(a,b,c){this.h=a;this.c=b;this.f=c;this.b=null;this.a=[]} +jc.prototype.g=function(a,b,c){this.b?this.b(a,b,c):this.a.push({response:a,complete:b,cb:c})};jc.prototype.abort=function(){this.c&&this.c.cancel();this.f&&this.f.abort()};function mc(a){switch(a){case 5:case 3:case 13:case 4:case 17:case 18:case 8:case 14:case 31:return 0;case 1:case 6:case 16:case 30:return 1;case 9:case 11:case 12:return 2;case 2:case 7:case 15:return 5;default:return-1}};var nc=p("Firefox"),oc=ya()||p("iPod"),pc=p("iPad"),qc=p("Android")&&!(xa()||p("Firefox")||p("Opera")||p("Silk")),rc=xa(),sc=p("Safari")&&!(xa()||p("Coast")||p("Opera")||p("Edge")||p("Silk")||p("Android"))&&!(ya()||p("iPad")||p("iPod"));var tc=null,uc=null;function vc(a){var b=a.length,c=0;"="===a[b-2]?c=2:"="===a[b-1]&&(c=1);var d=new Uint8Array(Math.ceil(3*b/4)-c),e=0;wc(a,function(a){d[e++]=a});return d.subarray(0,e)} +function wc(a,b){function c(b){for(;d<a.length;){var c=a.charAt(d++),e=uc[c];if(null!=e)return e;if(!/^[\s\xa0]*$/.test(c))throw Error("Unknown base64 encoding at char: "+c);}return b}xc();for(var d=0;;){var e=c(-1),f=c(0),g=c(64),h=c(64);if(64===h&&-1===e)break;b(e<<2|f>>4);64!=g&&(b(f<<4&240|g>>2),64!=h&&b(g<<6&192|h))}} +function xc(){if(!tc){tc={};uc={};for(var a=0;65>a;a++)tc[a]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(a),uc[tc[a]]=a,62<=a&&(uc["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.".charAt(a)]=a)}};function yc(a,b){var c=b&2147483648;c&&(a=~a+1>>>0,b=~b>>>0,0==a&&(b=b+1>>>0));a=4294967296*b+a;return c?-a:a};function zc(a,b,c){this.c=this.h=this.a=null;this.g=0;this.b=null;this.f=!0;Ac(this,a,b,c)}function Ac(a,b,c,d){b&&c&&(a.a=b,a.h=c);a.c=d||null;a.g=0;a.b=null;a.f=!a.a&&!a.c;a.next()}var Bc=[];function Cc(a,b,c){if(Bc.length){var d=Bc.pop();Ac(d,a,b,c);return d}return new zc(a,b,c)}function Dc(a){a.clear();100>Bc.length&&Bc.push(a)}zc.prototype.clear=function(){this.a&&Ec(this.a);this.c=this.h=this.a=null;this.g=0;this.b=null;this.f=!0};zc.prototype.get=function(){return this.b};zc.prototype.V=function(){return this.f}; +zc.prototype.next=function(){var a=this.b;this.a?this.a.V()?(this.b=null,this.f=!0):this.b=this.h.call(this.a):this.c&&(this.g==this.c.length?(this.b=null,this.f=!0):this.b=this.c[this.g++]);return a};function Fc(a,b,c){this.b=null;this.f=this.g=this.a=this.c=this.h=0;this.i=!1;a&&Gc(this,a,b,c)}var Hc=[];function Ic(a,b,c){if(Hc.length){var d=Hc.pop();a&&Gc(d,a,b,c);return d}return new Fc(a,b,c)}function Ec(a){a.clear();100>Hc.length&&Hc.push(a)}k=Fc.prototype; +k.clear=function(){this.b=null;this.a=this.c=this.h=0;this.i=!1};function Gc(a,b,c,d){b=b.constructor===Uint8Array?b:b.constructor===ArrayBuffer?new Uint8Array(b):b.constructor===Array?new Uint8Array(b):b.constructor===String?vc(b):new Uint8Array(0);a.b=b;a.h=m(c)?c:0;a.c=m(d)?a.h+d:a.b.length;a.a=a.h}k.reset=function(){this.a=this.h};k.V=function(){return this.a==this.c};k.getError=function(){return this.i||0>this.a||this.a>this.c}; +function Jc(a){for(var b,c=0,d,e=0;4>e;e++)if(b=a.b[a.a++],c|=(b&127)<<7*e,128>b){a.g=c>>>0;a.f=0;return}b=a.b[a.a++];c|=(b&127)<<28;d=0|(b&127)>>4;if(128>b)a.g=c>>>0,a.f=d>>>0;else{for(e=0;5>e;e++)if(b=a.b[a.a++],d|=(b&127)<<7*e+3,128>b){a.g=c>>>0;a.f=d>>>0;return}a.i=!0}} +k.S=function(){var a=this.b;var b=a[this.a+0];var c=b&127;if(128>b)return this.a+=1,c;b=a[this.a+1];c|=(b&127)<<7;if(128>b)return this.a+=2,c;b=a[this.a+2];c|=(b&127)<<14;if(128>b)return this.a+=3,c;b=a[this.a+3];c|=(b&127)<<21;if(128>b)return this.a+=4,c;b=a[this.a+4];c|=(b&15)<<28;if(128>b)return this.a+=5,c>>>0;this.a+=5;128<=a[this.a++]&&128<=a[this.a++]&&128<=a[this.a++]&&128<=a[this.a++]&&this.a++;return c};k.Pa=Fc.prototype.S;function Kc(a){a=a.S();return a>>>1^-(a&1)} +function Lc(a){Jc(a);return yc(a.g,a.f)}function t(a){var b=a.b[a.a+0],c=a.b[a.a+1],d=a.b[a.a+2],e=a.b[a.a+3];a.a+=4;return(b<<0|c<<8|d<<16|e<<24)>>>0}function Mc(a){var b=t(a);a=2*(b>>31)+1;var c=b>>>23&255;b&=8388607;return 255==c?b?NaN:Infinity*a:0==c?a*Math.pow(2,-149)*b:a*Math.pow(2,c-150)*(b+Math.pow(2,23))} +function Nc(a){var b=t(a),c=t(a);a=2*(c>>31)+1;var d=c>>>20&2047;b=4294967296*(c&1048575)+b;return 2047==d?b?NaN:Infinity*a:0==d?a*Math.pow(2,-1074)*b:a*Math.pow(2,d-1075)*(b+4503599627370496)};function Oc(a,b,c){this.b=Ic(a,b,c);this.c=this.b.a;this.f=this.a=-1;this.g=!1}var Pc=[];function Qc(a,b,c){if(Pc.length){var d=Pc.pop();a&&Gc(d.b,a,b,c);return d}return new Oc(a,b,c)}function Rc(a){a.b.clear();a.a=-1;a.f=-1;a.g=!1;100>Pc.length&&Pc.push(a)}Oc.prototype.getError=function(){return this.g||this.b.getError()};Oc.prototype.reset=function(){this.b.reset();this.f=this.a=-1}; +function u(a){if(a.b.V()||a.getError())return!1;a.c=a.b.a;var b=a.b.S(),c=b&7;if(0!=c&&5!=c&&1!=c&&2!=c&&3!=c&&4!=c)return a.g=!0,!1;a.a=b>>>3;a.f=c;return!0}function w(a){if(2!=a.f)x(a);else{var b=a.b.S();a=a.b;a.a+=b}} +function x(a){switch(a.f){case 0:if(0!=a.f)x(a);else{for(a=a.b;a.b[a.a]&128;)a.a++;a.a++}break;case 1:1!=a.f?x(a):(a=a.b,a.a+=8);break;case 2:w(a);break;case 5:5!=a.f?x(a):(a=a.b,a.a+=4);break;case 3:var b=[a.a];do{if(!u(a)){a.g=!0;break}if(3==a.f)b.push(a.a);else if(4==a.f&&a.a!=b.pop()){a.g=!0;break}}while(0<b.length)}} +function Sc(a,b){a.f=mc(b);switch(b){case 1:return Nc(a.b);case 2:return Mc(a.b);case 3:return Lc(a.b);case 4:return a=a.b,Jc(a),4294967296*a.f+a.g;case 5:return y(a);case 6:return a=a.b,b=t(a),4294967296*t(a)+b;case 7:return t(a.b);case 8:return z(a);case 9:return A(a);case 10:case 11:case 12:return Tc(a);case 13:return B(a);case 14:return C(a);case 15:a=a.b;b=a.b[a.a+0];var c=a.b[a.a+1],d=a.b[a.a+2],e=a.b[a.a+3];a.a+=4;return b<<0|c<<8|d<<16|e<<24;case 16:return b=a.b,a=t(b),b=t(b),yc(a,b);case 17:return Kc(a.b); +case 18:return b=a.b,Jc(b),a=b.g,c=b.f,b=a&1,a=(a>>>1|c<<31)>>>0,c>>>=1,b&&(a=a+1>>>0,0==a&&(c=c+1>>>0)),a=4294967296*c+a,b?-a:a;case 30:return D(a);case 31:return E(a)}return 0}function G(a,b,c){var d=a.b.c,e=a.b.S();e=a.b.a+e;a.b.c=e;c(b,a);a.b.a=e;a.b.c=d}function y(a){return a.b.Pa()}function B(a){return a.b.S()}function z(a){return!!a.b.S()}function C(a){return Lc(a.b)} +function A(a){var b=a.b.S();a=a.b;var c=a.b,d=a.a,e=d+b,f=[];for(b="";d<e;){var g=c[d++];if(128>g)f.push(g);else if(192>g)continue;else if(224>g){var h=c[d++];f.push((g&31)<<6|h&63)}else if(240>g){h=c[d++];var r=c[d++];f.push((g&15)<<12|(h&63)<<6|r&63)}else if(248>g){h=c[d++];r=c[d++];var v=c[d++];g=(g&7)<<18|(h&63)<<12|(r&63)<<6|v&63;g-=65536;f.push((g>>10&1023)+55296,(g&1023)+56320)}8192<=f.length&&(b+=String.fromCharCode.apply(null,f),f.length=0)}if(8192>=f.length)f=String.fromCharCode.apply(null, +f);else{c="";for(e=0;e<f.length;e+=8192)c+=String.fromCharCode.apply(null,pa(f,e,e+8192));f=c}a.a=d;return b+f}function Tc(a){var b=a.b.S();a=a.b;if(0>b||a.a+b>a.b.length)a.i=!0,b=new Uint8Array(0);else{var c=a.b.subarray(a.a,a.a+b);a.a+=b;b=c}return b}function E(a){var b=a.b;Jc(b);a=b.g;b=b.f;return String.fromCharCode(a>>>0&255,a>>>8&255,a>>>16&255,a>>>24&255,b>>>0&255,b>>>8&255,b>>>16&255,b>>>24&255)} +function D(a){a=a.b;var b=a.b,c=a.a,d=b[c+0],e=b[c+1],f=b[c+2],g=b[c+3],h=b[c+4],r=b[c+5],v=b[c+6];b=b[c+7];a.a+=8;return String.fromCharCode(d,e,f,g,h,r,v,b)};function Uc(a,b,c,d,e,f,g){this.g=a;this.a=b;this.b=m(c)?c:null;this.i=m(d)?d:null;this.h=m(e)?e:null;this.c=m(f)?f:null;this.f=m(g)?g:null}function Vc(){this.c=-1;this.value=this.a=this.b=this.start=this.buffer=null}var Wc=[],Xc=0;function Yc(a){if(a){null!=a.buffer&&null!=a.start&&null!=a.b&&null!=a.a&&null!=a.value&&(a.a.i&&a.a.i(a.value),a.value=null);a.c=-1;a.buffer=null;a.start=null;a.b=null;a.a=null;a.value=null;var b=Xc;1E3>b&&(Wc[b]=a,Xc++)}} +function Zc(a){if(null==a)return null;for(var b=[],c=0;c<a.length;c++){var d=a[c],e=new Vc;e.c=d.c;null!=d.value&&null!=d.a?(e.a=d.a,d.a.c?e.value=d.a.c(d.value):12==d.a.a?e.value=new Uint8Array(d.value):e.value=d.value):null!=d.buffer&&null!=d.start&&null!=d.b&&(e.buffer=new Uint8Array(d.buffer.buffer.slice(d.start,d.b)),e.start=0,e.b=d.b-d.start);b.push(e)}return b}function H(a,b,c,d,e,f,g,h){c=new Uc(b,c,d,e,f,g,h);for(d=0;d<a.length;d++)if(a[d].g==b){a[d]=c;return}a.push(c)};function $c(a,b,c){var d=Fc.prototype.Pa;return a&&null!=b&&null!=c&&d?(a=Ic(a,b,c-b),a.S(),a.S(),Cc(a,d,null)):Cc()}function I(a){return a?a.slice():null}function J(a,b){if(null===a)return null;for(var c=[],d=0;d<a.length;d++)c.push(b(a[d]));return c}function L(a,b){var c=a?a.length:0;if(c!=(b?b.length:0))return!1;for(var d=0;d<c;++d)if(a[d]!=b[d])return!1;return!0}function M(a,b,c){var d=a?a.length:0;if(d!=(b?b.length:0))return!1;for(var e=0;e<d;++e)if(!c(a[e],b[e]))return!1;return!0} +function ad(a,b){var c=a?a.length:0;if(c!=(b?b.length:0))return!1;for(var d=0;d<c;d++){var e=a[d],f=b[d];if(e.a!==f.a)return!1;if(e.a.f){if(!e.a.f(e.value,f.value))return!1}else if(12==e.a.a){if(!L(e.value,f.value))return!1}else if(e.value!=f.value)return!1}return!0}function bd(a,b,c){var d=Fc.prototype.Pa;if(a&&null!=b&&null!=c){a=Ic(a,b,c-b);a.S();a.S();for(b=[];!a.V();)b.push(d.call(a));Ec(a);return b}return null} +function cd(a,b,c){return a&&null!=b&&null!=c?(a=Qc(a,b,c-b),u(a),b=Tc(a),Rc(a),b):null}function P(a,b){if(!a)return null;a:{for(var c=0;c<a.length;c++)if(a[c].c==b){a=a[c];break a}a=null}a&&a.a?a.value?a=a.value:null==a||null==a.a||null==a.buffer||null==a.start||null==a.b?a=null:(b=Qc(a.buffer,a.start,a.b-a.start),u(b),a.a.b&&a.a.h?(a.value=a.a.b(),G(b,a.value,a.a.h)):a.value=Sc(b,a.a.a),Rc(b),a.buffer=null,a.start=null,a.b=null,a=a.value):a=null;return a} +function Q(a,b){var c=a.a,d=a.b.b,e=a.c;x(a);a=a.b.a;var f=null;if(b)for(var g=0;g<b.length;g++){var h=b[g];if(h.g==c){f=h;break}}b=f;Xc?(Xc--,f=Wc[Xc],Wc[Xc]=null):f=new Vc;g=f;g.c=c;g.buffer=m(d)?d:null;g.start=m(e)?e:null;g.b=m(a)?a:null;g.a=m(b)?b:null;g.value=null;return f};function dd(){this.b=this.a=null}dd.prototype.getExtension=function(){return null};function ed(a,b){for(;u(b);)switch(b.a){case 1:var c=C(b);a.a=c;break;case 2:c=A(b);a.b=c;break;default:x(b)}};function fd(){this.b=this.a=null}function gd(){this.a=null}fd.prototype.getExtension=function(){return null};function hd(){return new fd}function id(a){if(null===a)a=null;else{var b=new fd;if(b.a)for(var c=0;c<b.a.length;c++){var d=b.a[c];d&&jd(d)}b.a=null;b.b=null;b.a=J(a.a,kd);b.b=a.b;a=b}return a}function ld(){}function md(a,b){for(;u(b);)switch(b.a){case 1:var c=new gd;G(b,c,nd);a.a=a.a||[];a.a.push(c);break;case 2:c=A(b);a.b=c;break;default:x(b)}} +function od(a,b){return a===b?!0:null===a||null===b?!1:M(a.a,b.a,pd)&&a.b===b.b?!0:!1}function jd(a){var b=a.a;b&&(b.a=null,b.b=null);a.a=null}gd.prototype.getExtension=function(){return null};function kd(a){if(null===a)var b=null;else{b=new gd;jd(b);if(a.a){var c=new dd;a=a.a;c.a=null;c.b=null;c.a=a.a;c.b=a.b}else c=null;b.a=c}return b}function nd(a,b){for(;u(b);)switch(b.a){case 3:var c=new dd;G(b,c,ed);a.a=c;break;default:x(b)}} +function pd(a,b){a===b?b=!0:null===a||null===b?b=!1:(a=a.a,b=b.a,b=a===b||(null===a||null===b?0:a.a===b.a&&a.b===b.b)?!0:!1);return b};function qd(){this.a=this.b=null}qd.prototype.getExtension=function(){return null};function rd(a,b){for(;u(b);)switch(b.a){case 1:var c=C(b);a.b=c;break;case 2:c=A(b);a.a=c;break;default:x(b)}};function sd(){this.b=this.a=null}function td(a){var b=a.a;b&&(b.b=null,b.a=null);a.a=null;a.b=null}sd.prototype.getExtension=function(){return null};function ud(a,b){for(;u(b);)switch(b.a){case 1:var c=new qd;G(b,c,rd);a.a=c;break;case 2:c=z(b);a.b=c;break;default:x(b)}};function vd(){this.a=null}function wd(a){var b=a.a;b&&td(b);a.a=null}vd.prototype.getExtension=function(){return null};function xd(a,b){for(;u(b);)switch(b.a){case 15:var c=new sd;G(b,c,ud);a.a=c;break;default:x(b)}};function yd(){this.a=null}function zd(a){if(a.a)for(var b=0;b<a.a.length;b++)Yc(a.a[b]);a.a=null}var Ad=[];yd.prototype.getExtension=function(a){var b=!1;4<=a&&2147483647>a&&(b=!0);return b?P(this.a,a):null};function Bd(a,b){for(;u(b);){a.a=a.a||[];var c=Q(b,Ad);a.a.push(c)}};function Cd(){this.a=this.b=this.f=this.c=null}function Dd(a){var b=new Cd;Ed(b);b.c=a.c;b.f=a.f;if(a.b){var c=new yd;var d=a.b;zd(c);c.a=Zc(d.a)}else c=null;b.b=c;if(a.a){c=new vd;d=a.a;wd(c);if(d.a){a=new sd;d=d.a;td(a);if(d.a){var e=new qd;var f=d.a;e.b=null;e.a=null;e.b=f.b;e.a=f.a}else e=null;a.a=e;a.b=d.b}else a=null;c.a=a}else c=null;b.a=c;return b}function Ed(a){a.c=null;a.f=null;var b=a.b;b&&zd(b);a.b=null;(b=a.a)&&wd(b);a.a=null}Cd.prototype.getExtension=function(){return null}; +function Fd(a,b){for(;u(b);)switch(b.a){case 1:var c=t(b.b);a.c=c;break;case 2:c=t(b.b);a.f=c;break;case 15:c=new yd;G(b,c,Bd);a.b=c;break;case 500:c=new vd;G(b,c,xd);a.a=c;break;default:x(b)}} +function Gd(a,b){if(a===b)b=!0;else if(null===a||null===b)b=!1;else{var c;if(c=a.c===b.c&&a.f===b.f){c=a.b;var d=b.b;c=c===d?!0:null===c||null===d?!1:ad(c.a,d.a)?!0:!1}c&&(a=a.a,c=b.a,a===c?b=!0:null===a||null===c?b=!1:(b=a.a,a=c.a,(c=b===a)||(null===b||null===a?b=0:(c=b.a,d=a.a,b=(c===d?!0:null===c||null===d?!1:c.b!==d.b||c.a!==d.a?!1:!0)&&b.b===a.b),c=b),b=c?!0:!1),c=b);b=c?!0:!1}return b};function Hd(){this.a=this.b=null}function Id(a){var b=a.b;b&&Ed(b);a.b=null;(b=a.a)&&Ed(b);a.a=null}Hd.prototype.getExtension=function(){return null};function Jd(a,b){for(;u(b);)switch(b.a){case 1:var c=new Cd;G(b,c,Fd);a.b=c;break;case 2:c=new Cd;G(b,c,Fd);a.a=c;break;default:x(b)}};function Kd(){this.a=this.b=this.c=null}function Ld(){this.b=this.a=null}function Md(a){var b=new Kd;Nd(b);b.c=a.c;b.b=a.b;b.a=a.a;return b}function Nd(a){a.c=null;a.b=null;a.a=null}Kd.prototype.getExtension=function(){return null};function Od(a,b){for(;u(b);)switch(b.a){case 1:var c=E(b);a.c=c;break;case 2:c=t(b.b);a.b=c;break;case 3:c=t(b.b);a.a=c;break;default:x(b)}}function Pd(a,b){return a===b?!0:null===a||null===b?!1:a.c!==b.c||a.b!==b.b||a.a!==b.a?!1:!0} +function Qd(a){var b=new Ld;Rd(b);b.a=a.a?Md(a.a):null;b.b=a.b;return b}function Rd(a){var b=a.a;b&&Nd(b);a.a=null;a.b=null}Ld.prototype.getExtension=function(){return null};function Sd(a,b){for(;u(b);)switch(b.a){case 1:var c=new Kd;G(b,c,Od);a.a=c;break;case 2:c=E(b);a.b=c;break;default:x(b)}}function Td(a,b){return a===b?!0:null===a||null===b?!1:Pd(a.a,b.a)&&a.b===b.b?!0:!1};function Ud(){this.f=this.c=this.a=this.b=null}function Vd(a){var b=a.b;b&&Nd(b);a.b=null;(b=a.a)&&Rd(b);a.a=null;a.c=null;a.f=null}Ud.prototype.getExtension=function(){return null};function Wd(a,b){for(;u(b);)switch(b.a){case 1:var c=new Kd;G(b,c,Od);a.b=c;break;case 2:c=new Ld;G(b,c,Sd);a.a=c;break;case 3:c=y(b);a.c=c;break;case 4:c=C(b);a.f=c;break;default:x(b)}};function Xd(){this.a=null}Xd.prototype.getExtension=function(){return null};function Yd(a,b){for(;u(b);)switch(b.a){case 1:a.a=C(b);break;default:x(b)}};function Zd(){this.g=this.h=this.ya=this.za=this.v=this.ga=this.fa=this.B=this.b=this.l=this.Fa=this.f=this.X=this.o=this.M=this.A=this.Y=this.wa=this.va=this.Ba=this.$=this.C=this.D=this.F=this.G=this.ia=this.sa=this.ma=this.c=this.L=this.Ea=this.ha=this.Aa=this.oa=this.w=this.pa=this.na=this.m=this.ua=this.la=this.j=this.s=this.N=this.I=this.O=this.qa=this.ca=this.da=this.W=this.ea=this.ka=this.K=this.Z=this.T=this.aa=this.J=this.P=this.ba=this.R=this.ra=this.ta=this.Ca=this.a=this.i=this.ja=this.u= +this.H=this.Da=null}function $d(){this.a=this.c=this.b=null}function ae(){this.c=this.f=this.a=this.b=this.g=null}function be(){this.b=this.g=this.a=this.f=this.m=this.l=this.j=this.c=this.i=this.h=null}function ce(){this.a=null}function de(){this.a=this.b=null}function ee(){this.b=this.a=this.c=null}function fe(){this.c=this.g=this.b=this.a=this.h=this.f=null}function ge(){this.b=this.f=this.c=this.a=null}function he(){this.f=this.c=this.b=this.a=this.g=null} +function ie(){this.c=this.f=this.h=this.g=this.i=this.j=this.a=this.m=this.l=this.b=this.o=null}function je(){this.a=this.b=null}function ke(){this.a=this.c=this.b=null}function le(){this.b=this.c=this.a=null}function me(){this.b=this.a=null}function ne(){this.a=this.b=this.g=this.f=this.c=null} +function oe(a,b){for(;u(b);)switch(b.a){case 1:var c=C(b);a.Da=c;break;case 2:c=A(b);a.H=c;break;case 3:c=new $d;G(b,c,pe);a.u=c;break;case 4:c=A(b);a.ja=c;break;case 5:c=new be;G(b,c,qe);a.i=c;break;case 6:c=new be;G(b,c,qe);a.a=a.a||[];a.a.push(c);break;case 7:c=z(b);a.Ca=c;break;case 8:c=B(b);a.ta=c;break;case 9:c=B(b);a.ra=c;break;case 10:c=B(b);a.R=c;break;case 11:c=B(b);a.ba=c;break;case 12:c=B(b);a.P=c;break;case 13:c=B(b);a.J=c;break;case 14:c=B(b);a.aa=c;break;case 15:c=B(b);a.T=c;break; +case 16:c=B(b);a.Z=c;break;case 17:c=B(b);a.K=c;break;case 18:c=B(b);a.ka=c;break;case 19:c=B(b);a.ea=c;break;case 20:c=B(b);a.W=c;break;case 21:c=A(b);a.da=c;break;case 22:c=B(b);a.ca=c;break;case 23:c=C(b);a.qa=c;break;case 24:c=B(b);a.O=c;break;case 25:c=B(b);a.I=c;break;case 26:c=A(b);a.N=c;break;case 27:c=new fe;G(b,c,re);a.s=c;break;case 28:c=new ee;G(b,c,se);a.j=c;break;case 29:c=C(b);a.la=c;break;case 30:c=C(b);a.ua=c;break;case 31:c=C(b);a.m=a.m||[];a.m.push(c);break;case 32:c=B(b);a.na= +c;break;case 33:c=A(b);a.pa=c;break;case 34:c=B(b);a.w=c;break;case 35:c=B(b);a.oa=c;break;case 36:c=B(b);a.Aa=c;break;case 37:c=B(b);a.ha=c;break;case 38:c=z(b);a.Ea=c;break;case 39:c=C(b);a.L=c;break;case 40:c=new be;G(b,c,qe);a.c=a.c||[];a.c.push(c);break;case 41:c=A(b);a.ma=c;break;case 42:c=A(b);a.sa=c;break;case 43:c=z(b);a.ia=c;break;case 44:c=B(b);a.G=c;break;case 45:c=B(b);a.F=c;break;case 46:c=B(b);a.D=c;break;case 47:c=B(b);a.C=c;break;case 48:c=B(b);a.$=c;break;case 49:c=B(b);a.Ba=c;break; +case 50:c=B(b);a.va=c;break;case 51:c=B(b);a.wa=c;break;case 52:c=B(b);a.Y=c;break;case 53:c=B(b);a.A=c;break;case 54:c=B(b);a.M=c;break;case 55:c=new ie;G(b,c,te);a.o=c;break;case 56:c=B(b);a.X=c;break;case 57:c=new le;G(b,c,ue);a.f=a.f||[];a.f.push(c);break;case 58:c=B(b);a.Fa=c;break;case 59:c=new je;G(b,c,ve);a.l=c;break;case 60:c=new ke;G(b,c,we);a.b=a.b||[];a.b.push(c);break;case 62:c=B(b);a.B=c;break;case 63:c=B(b);a.fa=c;break;case 64:c=B(b);a.ga=c;break;case 65:c=new me;G(b,c,xe);a.v=c;break; +case 66:c=B(b);a.za=c;break;case 67:c=B(b);a.ya=c;break;case 68:c=new ne;G(b,c,ye);a.h=c;break;case 69:c=new de;G(b,c,ze);a.g=a.g||[];a.g.push(c);break;default:x(b)}} +function Ae(a,b){Be(a);a.Da=b.Da;a.H=b.H;a.u=b.u?Ce(b.u):null;a.ja=b.ja;a.i=b.i?De(b.i):null;a.a=J(b.a,Ee);a.Ca=b.Ca;a.ta=b.ta;a.ra=b.ra;a.R=b.R;a.ba=b.ba;a.P=b.P;a.J=b.J;a.aa=b.aa;a.T=b.T;a.Z=b.Z;a.K=b.K;a.ka=b.ka;a.ea=b.ea;a.W=b.W;a.da=b.da;a.ca=b.ca;a.qa=b.qa;a.O=b.O;a.I=b.I;a.N=b.N;a.s=b.s?Fe(b.s):null;a.j=b.j?Ge(b.j):null;a.la=b.la;a.ua=b.ua;a.m=I(b.m);a.na=b.na;a.pa=b.pa;a.w=b.w;a.oa=b.oa;a.Aa=b.Aa;a.ha=b.ha;a.Ea=b.Ea;a.L=b.L;a.c=J(b.c,Ee);a.ma=b.ma;a.sa=b.sa;a.ia=b.ia;a.G=b.G;a.F=b.F;a.D=b.D; +a.C=b.C;a.$=b.$;a.Ba=b.Ba;a.va=b.va;a.wa=b.wa;a.Y=b.Y;a.A=b.A;a.M=b.M;a.o=b.o?He(b.o):null;a.X=b.X;a.f=J(b.f,Ie);a.Fa=b.Fa;a.l=b.l?Je(b.l):null;a.b=J(b.b,Ke);a.B=b.B;a.fa=b.fa;a.ga=b.ga;a.v=b.v?Le(b.v):null;a.za=b.za;a.ya=b.ya;a.h=b.h?Me(b.h):null;a.g=J(b.g,Ne)} +function Be(a){a.Da=null;a.H=null;Oe(a.u);a.u=null;a.ja=null;Pe(a.i);a.i=null;if(a.a)for(var b=0;b<a.a.length;b++)Pe(a.a[b]);a.a=null;a.Ca=null;a.ta=null;a.ra=null;a.R=null;a.ba=null;a.P=null;a.J=null;a.aa=null;a.T=null;a.Z=null;a.K=null;a.ka=null;a.ea=null;a.W=null;a.da=null;a.ca=null;a.qa=null;a.O=null;a.I=null;a.N=null;Qe(a.s);a.s=null;Re(a.j);a.j=null;a.la=null;a.ua=null;a.m=null;a.na=null;a.pa=null;a.w=null;a.oa=null;a.Aa=null;a.ha=null;a.Ea=null;a.L=null;if(a.c)for(b=0;b<a.c.length;b++)Pe(a.c[b]); +a.c=null;a.ma=null;a.sa=null;a.ia=null;a.G=null;a.F=null;a.D=null;a.C=null;a.$=null;a.Ba=null;a.va=null;a.wa=null;a.Y=null;a.A=null;a.M=null;Se(a.o);a.o=null;a.X=null;if(a.f)for(b=0;b<a.f.length;b++)Te(a.f[b]);a.f=null;a.Fa=null;Ue(a.l);a.l=null;if(a.b)for(b=0;b<a.b.length;b++)Ve(a.b[b]);a.b=null;a.B=null;a.fa=null;a.ga=null;We(a.v);a.v=null;a.za=null;a.ya=null;Xe(a.h);a.h=null;if(a.g)for(b=0;b<a.g.length;b++)Ye(a.g[b]);a.g=null}Zd.prototype.getExtension=function(){return null}; +function Ze(a,b){oe(a,b)}function Ce(a){var b=new $d;b.b=null;b.c=null;b.a=null;b.b=a.b;b.c=a.c;b.a=a.a;return b}$d.prototype.getExtension=function(){return null};function Oe(a){a&&(a.b=null,a.c=null,a.a=null)}function pe(a,b){for(;u(b);)switch(b.a){case 1:var c=A(b);a.b=c;break;case 2:c=z(b);a.c=c;break;case 3:c=y(b);a.a=c;break;default:x(b)}}function $e(a){a.g=null;a.b=null;a.a=null;a.f=null;a.c=null}ae.prototype.getExtension=function(){return null}; +function af(a,b){for(;u(b);)switch(b.a){case 1:var c=Nc(b.b);a.g=c;break;case 2:c=B(b);a.b=c;break;case 3:c=B(b);a.a=c;break;case 4:c=B(b);a.f=c;break;case 5:c=B(b);a.c=c;break;default:x(b)}}function De(a){var b=new be;bf(b);b.h=a.h;b.i=a.i;b.c=I(a.c);b.j=a.j;b.l=a.l;b.m=a.m;b.f=a.f;b.a=J(a.a,cf);b.g=a.g;if(a.b){var c=new ae;a=a.b;$e(c);c.g=a.g;c.b=a.b;c.a=a.a;c.f=a.f;c.c=a.c}else c=null;b.b=c;return b} +function bf(a){a.h=null;a.i=null;a.c=null;a.j=null;a.l=null;a.m=null;a.f=null;if(a.a)for(var b=0;b<a.a.length;b++){var c=a.a[b];c&&(c.a=null)}a.a=null;a.g=null;(b=a.b)&&$e(b);a.b=null}be.prototype.getExtension=function(){return null};function Pe(a){a&&bf(a)}function Ee(a){return null===a?null:De(a)} +function qe(a,b){for(;u(b);)switch(b.a){case 1:var c=y(b);a.h=c;break;case 2:c=B(b);a.i=c;break;case 3:c=B(b);a.c=a.c||[];a.c.push(c);break;case 4:c=y(b);a.j=c;break;case 5:c=C(b);a.l=c;break;case 6:c=y(b);a.m=c;break;case 7:c=y(b);a.f=c;break;case 8:c=new ce;G(b,c,df);a.a=a.a||[];a.a.push(c);break;case 9:c=C(b);a.g=c;break;case 10:c=new ae;G(b,c,af);a.b=c;break;default:x(b)}} +function ef(a,b){if(a===b)b=!0;else if(null===a||null===b)b=!1;else{var c;if(c=a.h===b.h&&a.i===b.i&&L(a.c,b.c)&&a.j===b.j&&a.l===b.l&&a.m===b.m&&a.f===b.f&&M(a.a,b.a,ff)&&a.g===b.g)a=a.b,b=b.b,c=a===b?!0:null===a||null===b?!1:a.g!==b.g||a.b!==b.b||a.a!==b.a||a.f!==b.f||a.c!==b.c?!1:!0;b=c?!0:!1}return b}ce.prototype.getExtension=function(){return null};function cf(a){if(null===a)a=null;else{var b=new ce;b.a=null;b.a=a.a;a=b}return a} +function df(a,b){for(;u(b);)switch(b.a){case 1:a.a=C(b);break;default:x(b)}}function ff(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a?!1:!0}function gf(a){a.b=null;if(a.a)for(var b=0;b<a.a.length;b++)Pe(a.a[b]);a.a=null}de.prototype.getExtension=function(){return null};function Ye(a){a&&gf(a)}function Ne(a){if(null===a)a=null;else{var b=new de;gf(b);b.b=a.b;b.a=J(a.a,Ee);a=b}return a} +function ze(a,b){for(;u(b);)switch(b.a){case 1:var c=A(b);a.b=c;break;case 2:c=new be;G(b,c,qe);a.a=a.a||[];a.a.push(c);break;default:x(b)}}function hf(a,b){return a===b?!0:null===a||null===b?!1:a.b===b.b&&M(a.a,b.a,ef)?!0:!1}function Ge(a){var b=new ee;b.c=null;b.a=null;b.b=null;b.c=a.c;b.a=a.a;b.b=a.b;return b}ee.prototype.getExtension=function(){return null};function Re(a){a&&(a.c=null,a.a=null,a.b=null)} +function se(a,b){for(;u(b);)switch(b.a){case 1:var c=z(b);a.c=c;break;case 2:c=z(b);a.a=c;break;case 3:c=z(b);a.b=c;break;default:x(b)}}function Fe(a){var b=new fe;jf(b);b.f=a.f;b.h=a.h;b.a=a.a;b.b=a.b;b.g=a.g;b.c=a.c;return b}function jf(a){a.f=null;a.h=null;a.a=null;a.b=null;a.g=null;a.c=null}fe.prototype.getExtension=function(){return null};function Qe(a){a&&jf(a)} +function re(a,b){for(;u(b);)switch(b.a){case 1:var c=z(b);a.f=c;break;case 2:c=B(b);a.h=c;break;case 3:c=B(b);a.a=c;break;case 4:c=B(b);a.b=c;break;case 5:c=B(b);a.g=c;break;case 6:c=B(b);a.c=c;break;default:x(b)}}function kf(a){a.a=null;a.c=null;a.f=null;a.b=null}ge.prototype.getExtension=function(){return null};function lf(a,b){for(;u(b);)switch(b.a){case 1:var c=B(b);a.a=c;break;case 2:c=B(b);a.c=c;break;case 3:c=B(b);a.f=c;break;case 4:c=A(b);a.b=c;break;default:x(b)}} +function mf(a){a.g=null;a.a=null;a.b=null;a.c=null;a.f=null}he.prototype.getExtension=function(){return null};function nf(a){if(null===a)a=null;else{var b=new he;mf(b);b.g=a.g;b.a=a.a;b.b=a.b;b.c=a.c;b.f=a.f;a=b}return a}function of(a,b){for(;u(b);)switch(b.a){case 1:var c=z(b);a.g=c;break;case 2:c=z(b);a.a=c;break;case 3:c=z(b);a.b=c;break;case 4:c=B(b);a.c=c;break;case 5:c=B(b);a.f=c;break;default:x(b)}} +function pf(a,b){return a===b?!0:null===a||null===b?!1:a.g!==b.g||a.a!==b.a||a.b!==b.b||a.c!==b.c||a.f!==b.f?!1:!0}function He(a){var b=new ie;qf(b);b.o=a.o;if(a.b){var c=new ge;var d=a.b;kf(c);c.a=d.a;c.c=d.c;c.f=d.f;c.b=d.b}else c=null;b.b=c;b.l=a.l;b.m=a.m;b.a=J(a.a,nf);b.j=a.j;b.i=a.i;b.g=a.g;b.h=a.h;b.f=a.f;b.c=a.c;return b} +function qf(a){a.o=null;var b=a.b;b&&kf(b);a.b=null;a.l=null;a.m=null;if(a.a)for(b=0;b<a.a.length;b++){var c=a.a[b];c&&mf(c)}a.a=null;a.j=null;a.i=null;a.g=null;a.h=null;a.f=null;a.c=null}ie.prototype.getExtension=function(){return null};function Se(a){a&&qf(a)} +function te(a,b){for(;u(b);)switch(b.a){case 1:var c=y(b);a.o=c;break;case 2:c=new ge;G(b,c,lf);a.b=c;break;case 3:c=z(b);a.l=c;break;case 4:c=y(b);a.m=c;break;case 5:c=new he;G(b,c,of);a.a=a.a||[];a.a.push(c);break;case 6:c=y(b);a.j=c;break;case 7:c=y(b);a.i=c;break;case 8:c=y(b);a.g=c;break;case 9:c=y(b);a.h=c;break;case 10:c=y(b);a.f=c;break;case 11:c=y(b);a.c=c;break;default:x(b)}} +function rf(a,b){if(a===b)a=!0;else if(null===a||null===b)a=!1;else{var c;if(c=a.o===b.o){c=a.b;var d=b.b;c=c===d?!0:null===c||null===d?!1:c.a!==d.a||c.c!==d.c||c.f!==d.f||c.b!==d.b?!1:!0}a=c&&a.l===b.l&&a.m===b.m&&M(a.a,b.a,pf)&&a.j===b.j&&a.i===b.i&&a.g===b.g&&a.h===b.h&&a.f===b.f&&a.c===b.c?!0:!1}return a}function Je(a){var b=new je;b.b=null;b.a=null;b.b=a.b;b.a=a.a;return b}je.prototype.getExtension=function(){return null};function Ue(a){a&&(a.b=null,a.a=null)} +function ve(a,b){for(;u(b);)switch(b.a){case 1:var c=B(b);a.b=c;break;case 2:c=B(b);a.a=c;break;default:x(b)}}ke.prototype.getExtension=function(){return null};function Ve(a){a&&(a.b=null,a.c=null,a.a=null)}function Ke(a){if(null===a)a=null;else{var b=new ke;b.b=null;b.c=null;b.a=null;b.b=a.b;b.c=a.c;b.a=a.a;a=b}return a}function we(a,b){for(;u(b);)switch(b.a){case 1:var c=C(b);a.b=c;break;case 2:c=A(b);a.c=c;break;case 3:c=y(b);a.a=c;break;default:x(b)}} +function sf(a,b){return a===b?!0:null===a||null===b?!1:a.b!==b.b||a.c!==b.c||a.a!==b.a?!1:!0}le.prototype.getExtension=function(){return null};function Te(a){a&&(a.a=null,a.c=null,a.b=null)}function Ie(a){if(null===a)a=null;else{var b=new le;b.a=null;b.c=null;b.b=null;b.a=I(a.a);b.c=a.c;b.b=a.b;a=b}return a}function ue(a,b){for(;u(b);)switch(b.a){case 1:var c=B(b);a.a=a.a||[];a.a.push(c);break;case 2:c=B(b);a.c=c;break;case 3:c=y(b);a.b=c;break;default:x(b)}} +function tf(a,b){return a===b?!0:null===a||null===b?!1:L(a.a,b.a)&&a.c===b.c&&a.b===b.b?!0:!1}function Le(a){var b=new me;b.a=null;b.b=null;b.a=a.a;b.b=a.b;return b}me.prototype.getExtension=function(){return null};function We(a){a&&(a.a=null,a.b=null)}function xe(a,b){for(;u(b);)switch(b.a){case 1:var c=y(b);a.a=c;break;case 2:c=y(b);a.b=c;break;default:x(b)}}function Me(a){var b=new ne;uf(b);b.c=a.c;b.f=a.f;b.g=a.g;b.b=a.b;b.a=a.a;return b} +function uf(a){a.c=null;a.f=null;a.g=null;a.b=null;a.a=null}ne.prototype.getExtension=function(){return null};function Xe(a){a&&uf(a)}function ye(a,b){for(;u(b);)switch(b.a){case 1:var c=B(b);a.c=c;break;case 2:c=B(b);a.f=c;break;case 3:c=B(b);a.g=c;break;case 4:c=B(b);a.b=c;break;case 5:c=B(b);a.a=c;break;default:x(b)}};function vf(){this.b=this.a=null}vf.prototype.getExtension=function(){return null};function wf(a,b){for(;u(b);)switch(b.a){case 1:var c=y(b);a.a=a.a||[];a.a.push(c);break;case 2:c=y(b);a.b=c;break;default:x(b)}};function xf(){this.b=this.u=this.a=this.l=this.h=this.c=this.m=this.i=this.j=this.g=this.f=this.s=this.o=null}function yf(a){var b=new xf;zf(b);b.o=a.o;b.s=a.s;b.f=a.f;b.g=a.g;b.j=a.j;b.i=a.i;b.m=a.m;b.c=a.c;b.h=a.h;b.l=a.l;b.a=a.a?Qd(a.a):null;b.u=a.u;if(a.b){var c=new vf;a=a.b;c.a=null;c.b=null;c.a=I(a.a);c.b=a.b}else c=null;b.b=c;return b} +function zf(a){a.o=null;a.s=null;a.f=null;a.g=null;a.j=null;a.i=null;a.m=null;a.c=null;a.h=null;a.l=null;var b=a.a;b&&Rd(b);a.a=null;a.u=null;if(b=a.b)b.a=null,b.b=null;a.b=null}xf.prototype.getExtension=function(){return null}; +function Af(a,b){for(;u(b);)switch(b.a){case 1:var c=y(b);a.o=c;break;case 2:c=y(b);a.s=c;break;case 5:c=y(b);a.f=c;break;case 6:c=y(b);a.g=c;break;case 7:c=y(b);a.j=c;break;case 8:c=y(b);a.i=c;break;case 9:c=y(b);a.m=c;break;case 10:c=z(b);a.c=c;break;case 11:c=y(b);a.h=c;break;case 12:c=D(b);a.l=c;break;case 13:c=new Ld;G(b,c,Sd);a.a=c;break;case 14:c=y(b);a.u=c;break;case 15:c=new vf;G(b,c,wf);a.b=c;break;default:x(b)}} +function Bf(a,b){if(a===b)b=!0;else if(null===a||null===b)b=!1;else{var c;if(c=a.o===b.o&&a.s===b.s&&a.f===b.f&&a.g===b.g&&a.j===b.j&&a.i===b.i&&a.m===b.m&&a.c===b.c&&a.h===b.h&&a.l===b.l&&Td(a.a,b.a)&&a.u===b.u)a=a.b,b=b.b,c=a===b?!0:null===a||null===b?!1:L(a.a,b.a)&&a.b===b.b?!0:!1;b=c?!0:!1}return b};function Cf(){this.g=this.f=this.a=this.c=this.b=null}function Df(a){var b=a.b;b&&Nd(b);a.b=null;(b=a.c)&&zf(b);a.c=null;(b=a.a)&&Rd(b);a.a=null;a.f=null;a.g=null}Cf.prototype.getExtension=function(){return null};function Ef(a,b){for(;u(b);)switch(b.a){case 1:var c=new Kd;G(b,c,Od);a.b=c;break;case 2:c=new xf;G(b,c,Af);a.c=c;break;case 3:c=new Ld;G(b,c,Sd);a.a=c;break;case 4:c=A(b);a.f=c;break;case 5:c=A(b);a.g=c;break;default:x(b)}};function Ff(){this.a=null}function Gf(a){var b=a.a;b&&Df(b);a.a=null}Ff.prototype.getExtension=function(){return null};function Hf(a,b){for(;u(b);)switch(b.a){case 1:var c=new Cf;G(b,c,Ef);a.a=c;break;default:x(b)}};function If(){this.a=this.g=this.h=this.c=this.f=this.j=this.o=this.l=this.b=this.i=this.m=null}function Jf(a){a.m=null;a.i=null;a.b=null;a.l=null;a.o=null;a.j=null;var b=a.f;b&&Vd(b);a.f=null;(b=a.c)&&Gf(b);a.c=null;a.h=null;a.g=null;if(a.a)for(b=0;b<a.a.length;b++)Yc(a.a[b]);a.a=null}var Kf=[]; +If.prototype.getExtension=function(a){var b=!1;67<=a&&68>a&&(b=!0);259<=a&&260>a&&(b=!0);270<=a&&271>a&&(b=!0);271<=a&&272>a&&(b=!0);278<=a&&279>a&&(b=!0);234<=a&&235>a&&(b=!0);291<=a&&292>a&&(b=!0);292<=a&&293>a&&(b=!0);294<=a&&295>a&&(b=!0);296<=a&&297>a&&(b=!0);302<=a&&303>a&&(b=!0);304<=a&&305>a&&(b=!0);312<=a&&313>a&&(b=!0);313<=a&&314>a&&(b=!0);317<=a&&318>a&&(b=!0);319<=a&&320>a&&(b=!0);338<=a&&339>a&&(b=!0);355<=a&&356>a&&(b=!0);356<=a&&357>a&&(b=!0);363<=a&&364>a&&(b=!0);368<=a&&369>a&&(b= +!0);return b?P(this.a,a):null};function Lf(a){if(null===a)a=null;else{var b=new If;Jf(b);b.m=a.m;b.i=a.i;b.b=I(a.b);b.l=a.l;b.o=a.o;b.j=a.j;if(a.f){var c=new Ud;var d=a.f;Vd(c);c.b=d.b?Md(d.b):null;c.a=d.a?Qd(d.a):null;c.c=d.c;c.f=d.f}else c=null;b.f=c;if(a.c){c=new Ff;var e=a.c;Gf(c);e.a?(d=new Cf,e=e.a,Df(d),d.b=e.b?Md(e.b):null,d.c=e.c?yf(e.c):null,d.a=e.a?Qd(e.a):null,d.f=e.f,d.g=e.g):d=null;c.a=d}else c=null;b.c=c;b.h=I(a.h);b.g=I(a.g);b.a=Zc(a.a);a=b}return a} +function Mf(a,b){for(;u(b);)switch(b.a){case 1:var c=y(b);a.m=c;break;case 3:c=y(b);a.i=c;break;case 4:c=y(b);a.b=a.b||[];a.b.push(c);break;case 5:c=A(b);a.l=c;break;case 6:c=C(b);a.o=c;break;case 7:c=y(b);a.j=c;break;case 11:c=new Ud;G(b,c,Wd);a.f=c;break;case 232:c=new Ff;G(b,c,Hf);a.c=c;break;case 260:c=A(b);a.h=a.h||[];a.h.push(c);break;case 330:c=y(b);a.g=a.g||[];a.g.push(c);break;default:a.a=a.a||[],c=Q(b,Kf),a.a.push(c)}} +function Nf(a,b){if(a===b)a=!0;else if(null===a||null===b)a=!1;else{var c;if(c=a.m===b.m&&a.i===b.i&&L(a.b,b.b)&&a.l===b.l&&a.o===b.o&&a.j===b.j){c=a.f;var d=b.f;c=c===d?!0:null===c||null===d?!1:Pd(c.b,d.b)&&Td(c.a,d.a)&&c.c===d.c&&c.f===d.f?!0:!1}c&&(d=a.c,c=b.c,d===c?c=!0:null===d||null===c?c=!1:(d=d.a,c=c.a,c=d===c||(null===d||null===c?0:Pd(d.b,c.b)&&Bf(d.c,c.c)&&Td(d.a,c.a)&&d.f===c.f&&d.g===c.g)?!0:!1));a=c&&L(a.h,b.h)&&L(a.g,b.g)&&ad(a.a,b.a)?!0:!1}return a};function Of(){this.f=this.c=this.b=this.a=null}function Pf(){this.b=this.c=this.a=null}function Qf(){this.b=this.c=this.a=null}function Rf(){this.a=this.b=null}function Sf(a){var b=new Of;Tf(b);if(a.a){var c=a.a;var d=new Pf;d.a=null;d.c=null;d.b=null;d.a=c.a;d.c=c.c;d.b=c.b;c=d}else c=null;b.a=c;a.b?(c=a.b,d=new Qf,d.a=null,d.c=null,d.b=null,d.a=c.a,d.c=c.c,d.b=c.b,c=d):c=null;b.b=c;a.c?(c=a.c,d=new Rf,d.b=null,d.a=null,d.b=c.b,d.a=c.a,c=d):c=null;b.c=c;b.f=a.f;return b} +function Tf(a){var b=a.a;b&&(b.a=null,b.c=null,b.b=null);a.a=null;if(b=a.b)b.a=null,b.c=null,b.b=null;a.b=null;if(b=a.c)b.b=null,b.a=null;a.c=null;a.f=null}Of.prototype.getExtension=function(){return null};function Uf(a,b){for(;u(b);)switch(b.a){case 1:var c=new Pf;G(b,c,Vf);a.a=c;break;case 2:c=new Qf;G(b,c,Wf);a.b=c;break;case 3:c=new Rf;G(b,c,Xf);a.c=c;break;case 4:c=Mc(b.b);a.f=c;break;default:x(b)}} +function Yf(a,b){if(a===b)a=!0;else if(null===a||null===b)a=!1;else{var c=a.a,d=b.a;if(c=c===d?!0:null===c||null===d?!1:c.a!==d.a||c.c!==d.c||c.b!==d.b?!1:!0)c=a.b,d=b.b,c=c===d?!0:null===c||null===d?!1:c.a!==d.a||c.c!==d.c||c.b!==d.b?!1:!0;c&&(c=a.c,d=b.c,c=c===d?!0:null===c||null===d?!1:c.b!==d.b||c.a!==d.a?!1:!0);a=c&&a.f===b.f?!0:!1}return a}Pf.prototype.getExtension=function(){return null}; +function Vf(a,b){for(;u(b);)switch(b.a){case 1:var c=Nc(b.b);a.a=c;break;case 2:c=Nc(b.b);a.c=c;break;case 3:c=Nc(b.b);a.b=c;break;default:x(b)}}Qf.prototype.getExtension=function(){return null};function Wf(a,b){for(;u(b);)switch(b.a){case 1:var c=Mc(b.b);a.a=c;break;case 2:c=Mc(b.b);a.c=c;break;case 3:c=Mc(b.b);a.b=c;break;default:x(b)}}Rf.prototype.getExtension=function(){return null};function Xf(a,b){for(;u(b);)switch(b.a){case 1:var c=y(b);a.b=c;break;case 2:c=y(b);a.a=c;break;default:x(b)}};function Zf(){this.b=this.a=null}function $f(){this.b=this.a=null}function ag(){this.a=this.b=null}function bg(a){var b=new Zf;cg(b);b.a=a.a;b.b=a.b;return b}function cg(a){a.a=null;a.b=null}Zf.prototype.getExtension=function(){return null};function dg(a,b){for(;u(b);)switch(b.a){case 3:var c=Nc(b.b);a.a=c;break;case 4:c=Nc(b.b);a.b=c;break;default:x(b)}}function eg(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a||a.b!==b.b?!1:!0} +function fg(a){var b=new $f;b.a=null;b.b=null;b.a=a.a;b.b=a.b;return b}$f.prototype.getExtension=function(){return null};function gg(a,b){for(;u(b);)switch(b.a){case 1:var c=y(b);a.a=c;break;case 2:c=y(b);a.b=c;break;default:x(b)}}function hg(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a||a.b!==b.b?!1:!0}function ig(a){var b=a.b;b&&(b.a=null,b.b=null);a.b=null;if(b=a.a)b.a=null,b.b=null;a.a=null}ag.prototype.getExtension=function(){return null}; +function jg(a){if(null===a)a=null;else{var b=new ag;ig(b);b.b=a.b?fg(a.b):null;b.a=a.a?fg(a.a):null;a=b}return a}function kg(a,b){for(;u(b);)switch(b.a){case 1:var c=new $f;G(b,c,gg);a.b=c;break;case 2:c=new $f;G(b,c,gg);a.a=c;break;default:x(b)}}function lg(a,b){return a===b?!0:null===a||null===b?!1:hg(a.b,b.b)&&hg(a.a,b.a)?!0:!1};function mg(){this.v=this.u=this.f=this.a=this.o=this.l=this.h=this.j=this.i=this.g=this.b=this.c=this.s=this.m=null}function ng(a){var b=new mg;og(b);b.m=a.m;b.s=a.s;b.c=a.c?Sf(a.c):null;b.b=a.b?bg(a.b):null;b.g=a.g;b.i=a.i;b.j=a.j;b.h=a.h;b.l=a.l;b.o=a.o;b.a=a.a?new Uint8Array(a.a):null;b.f=a.f;b.u=a.u;b.v=a.v;return b}function og(a){a.m=null;a.s=null;var b=a.c;b&&Tf(b);a.c=null;(b=a.b)&&cg(b);a.b=null;a.g=null;a.i=null;a.j=null;a.h=null;a.l=null;a.o=null;a.a=null;a.f=null;a.u=null} +mg.prototype.getExtension=function(){return null};function pg(a,b){for(a.v=b.b.b;u(b);)switch(b.a){case 1:var c=A(b);a.m=c;break;case 2:c=A(b);a.s=c;break;case 3:c=new Of;G(b,c,Uf);a.c=c;break;case 4:c=new Zf;G(b,c,dg);a.b=c;break;case 5:c=C(b);a.g=c;break;case 6:c=z(b);a.i=c;break;case 7:c=z(b);a.j=c;break;case 9:c=C(b);a.h=c;break;case 10:c=y(b);a.l=c;break;case 11:c=A(b);a.o=c;break;case 12:null===a.f&&(a.f=b.c);w(b);a.u=b.b.a;break;default:x(b)}} +function qg(a,b){a===b?a=!0:null===a||null===b?a=!1:a.m===b.m&&a.s===b.s&&Yf(a.c,b.c)&&eg(a.b,b.b)&&a.g===b.g&&a.i===b.i&&a.j===b.j&&a.h===b.h&&a.l===b.l&&a.o===b.o?(null!=a.f&&null==a.a&&(a.a=cd(a.v,a.f,a.u)),a=L(a.a,b.a)?!0:!1):a=!1;return a};function rg(){this.c=this.h=this.b=this.i=this.f=this.a=this.g=null}function sg(){this.h=this.b=this.c=this.i=this.g=this.a=this.f=null}function tg(){this.a=this.b=null}function ug(){this.b=this.a=null}function vg(){this.c=this.a=this.f=this.b=null}function wg(){this.a=null}rg.prototype.getExtension=function(){return null};function xg(){return new rg} +function yg(a){if(null===a)var b=null;else{b=new rg;b.g=null;if(b.a)for(var c=0;c<b.a.length;c++){var d=b.a[c];d&&zg(d)}b.a=null;b.f=null;b.i=null;(c=b.b)&&Ed(c);b.b=null;b.h=null;(c=b.c)&&Ag(c);b.c=null;b.g=a.g;b.a=J(a.a,Bg);b.f=a.f;b.i=a.i;b.b=a.b?Dd(a.b):null;b.h=a.h;a.c?(a=a.c,c=new wg,Ag(c),c.a=a.a?Cg(a.a):null,a=c):a=null;b.c=a}return b}function Dg(){} +function Eg(a,b){for(;u(b);)switch(b.a){case 1:var c=A(b);a.g=c;break;case 2:c=new sg;G(b,c,Fg);a.a=a.a||[];a.a.push(c);break;case 3:c=y(b);a.f=c;break;case 4:c=z(b);a.i=c;break;case 5:c=new Cd;G(b,c,Fd);a.b=c;break;case 6:c=y(b);a.h=c;break;case 7:c=new wg;G(b,c,Gg);a.c=c;break;default:x(b)}} +function Hg(a,b){if(a===b)b=!0;else if(null===a||null===b)b=!1;else{var c;if(c=a.g===b.g&&M(a.a,b.a,Ig)&&a.f===b.f&&a.i===b.i&&Gd(a.b,b.b)&&a.h===b.h)a=a.c,b=b.c,c=a===b?!0:null===a||null===b?!1:Jg(a.a,b.a)?!0:!1;b=c?!0:!1}return b}function zg(a){a.f=null;a.a=null;a.g=null;a.i=null;a.c=null;var b=a.b;b&&Id(b);a.b=null;a.h=null}sg.prototype.getExtension=function(){return null}; +function Bg(a){if(null===a)a=null;else{var b=new sg;zg(b);b.f=a.f;b.a=I(a.a);b.g=a.g;b.i=a.i;b.c=a.c;if(a.b){var c=new Hd;var d=a.b;Id(c);c.b=d.b?Dd(d.b):null;c.a=d.a?Dd(d.a):null}else c=null;b.b=c;b.h=a.h;a=b}return a}function Fg(a,b){for(;u(b);)switch(b.a){case 1:var c=A(b);a.f=c;break;case 2:c=A(b);a.a=a.a||[];a.a.push(c);break;case 3:c=A(b);a.g=c;break;case 4:c=A(b);a.i=c;break;case 5:c=Kc(b.b);a.c=c;break;case 7:c=new Hd;G(b,c,Jd);a.b=c;break;case 8:c=Kc(b.b);a.h=c;break;default:x(b)}} +function Ig(a,b){if(a===b)a=!0;else if(null===a||null===b)a=!1;else{var c;if(c=a.f===b.f&&L(a.a,b.a)&&a.g===b.g&&a.i===b.i&&a.c===b.c){c=a.b;var d=b.b;c=c===d?!0:null===c||null===d?!1:Gd(c.b,d.b)&&Gd(c.a,d.a)?!0:!1}a=c&&a.h===b.h?!0:!1}return a}tg.prototype.getExtension=function(){return null};function Kg(){return new tg} +function Lg(a){if(null===a)a=null;else{var b=new tg;b.b=null;if(b.a)for(var c=0;c<b.a.length;c++){var d=b.a[c];d&&(d.a=null,d.b=null)}b.a=null;b.b=I(a.b);b.a=J(a.a,Mg);a=b}return a}function Ng(){}function Og(a,b){for(;u(b);)switch(b.a){case 1:var c=A(b);a.b=a.b||[];a.b.push(c);break;case 2:c=new ug;G(b,c,Pg);a.a=a.a||[];a.a.push(c);break;default:x(b)}}function Qg(a,b){return a===b?!0:null===a||null===b?!1:L(a.b,b.b)&&M(a.a,b.a,Rg)?!0:!1}ug.prototype.getExtension=function(){return null}; +function Mg(a){if(null===a)a=null;else{var b=new ug;b.a=null;b.b=null;b.a=a.a;b.b=a.b;a=b}return a}function Pg(a,b){for(;u(b);)switch(b.a){case 1:var c=A(b);a.a=c;break;case 2:c=Kc(b.b);a.b=c;break;default:x(b)}}function Rg(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a||a.b!==b.b?!1:!0}function Cg(a){var b=new vg;Sg(b);b.b=a.b;b.f=a.f;b.a=a.a?ng(a.a):null;b.c=a.c;return b}function Sg(a){a.b=null;a.f=null;var b=a.a;b&&og(b);a.a=null;a.c=null}vg.prototype.getExtension=function(){return null}; +function Tg(a,b){for(;u(b);)switch(b.a){case 1:var c=A(b);a.b=c;break;case 2:c=A(b);a.f=c;break;case 3:c=new mg;G(b,c,pg);a.a=c;break;case 4:c=A(b);a.c=c;break;default:x(b)}}function Jg(a,b){return a===b?!0:null===a||null===b?!1:a.b===b.b&&a.f===b.f&&qg(a.a,b.a)&&a.c===b.c?!0:!1}function Ag(a){var b=a.a;b&&Sg(b);a.a=null}wg.prototype.getExtension=function(){return null};function Gg(a,b){for(;u(b);)switch(b.a){case 1:var c=new vg;G(b,c,Tg);a.a=c;break;default:x(b)}};function Ug(){this.a=this.b=null}function Vg(){this.a=null}function Wg(){}function Xg(){this.a=null}function Yg(){this.a=null}function Zg(){this.a=this.f=this.c=this.i=this.h=this.b=this.g=null}function $g(){this.a=this.b=null}Ug.prototype.getExtension=function(){return null};function ah(a,b){for(;u(b);)switch(b.a){case 1:null===a.b&&(a.b=b.c);w(b);break;case 2:null===a.a&&(a.a=b.c);w(b);break;case 1E3:x(b);break;case 1001:x(b);break;default:x(b)}}Vg.prototype.getExtension=function(){return null}; +function bh(a,b){for(;u(b);)switch(b.a){case 1:null===a.a&&(a.a=b.c);w(b);break;case 2:y(b);break;case 3:y(b);break;case 4:y(b);break;case 1E3:x(b);break;default:x(b)}}Wg.prototype.getExtension=function(){return null};function ch(a,b){for(;u(b);)switch(b.a){case 1:a=new Ug;G(b,a,ah);break;case 2:C(b);break;case 4:y(b);break;case 5:a=new Vg;G(b,a,bh);break;default:x(b)}}Xg.prototype.getExtension=function(){return null}; +function dh(a,b){for(;u(b);)switch(b.a){case 1:null===a.a&&(a.a=b.c);w(b);break;case 2:y(b);break;case 3:y(b);break;case 4:C(b);break;case 5:y(b);break;case 1E3:x(b);break;default:x(b)}}Yg.prototype.getExtension=function(){return null};function eh(a,b){for(;u(b);)switch(b.a){case 1:var c=new Zg;G(b,c,fh);a.a=a.a||[];a.a.push(c);break;case 2:y(b);break;case 3:E(b);break;case 4:C(b);break;case 1E3:y(b);break;default:x(b)}}var gh=[]; +Zg.prototype.getExtension=function(a){var b=!1;25E6<=a&&536870912>a&&(b=!0);return b?P(this.a,a):null}; +function fh(a,b){for(;u(b);)switch(b.a){case 1:A(b);break;case 2:y(b);break;case 3:z(b);break;case 4:E(b);break;case 6:null===a.g&&(a.g=b.c);w(b);break;case 7:null===a.b&&(a.b=b.c);w(b);break;case 8:null===a.h&&(a.h=b.c);w(b);break;case 9:null===a.i&&(a.i=b.c);w(b);break;case 10:null===a.c&&(a.c=b.c);w(b);break;case 11:null===a.f&&(a.f=b.c);w(b);break;case 1E3:y(b);break;case 1001:A(b);break;default:a.a=a.a||[];var c=Q(b,gh);a.a.push(c)}}var R=[]; +$g.prototype.getExtension=function(a){var b=!1;25E6<=a&&536870912>a&&(b=!0);return b?P(this.a,a):null}; +function hh(a,b){for(;u(b);)switch(b.a){case 1:var c=new Yg;G(b,c,eh);break;case 2:c=new Yg;G(b,c,eh);break;case 3:c=new Wg;G(b,c,ch);break;case 4:c=new Xg;G(b,c,dh);break;case 5:E(b);break;case 6:B(b);break;case 7:C(b);break;case 8:y(b);break;case 9:y(b);break;case 10:t(b.b);break;case 11:y(b);break;case 12:y(b);break;case 13:y(b);break;case 14:y(b);break;case 15:D(b);break;case 16:null===a.b&&(a.b=b.c);w(b);break;case 1E3:y(b);break;default:a.a=a.a||[],c=Q(b,R),a.a.push(c)}};function ih(){this.a=this.b=null}function jh(){this.b=this.a=null}ih.prototype.getExtension=function(){return null};function kh(a,b){for(;u(b);)switch(b.a){case 1:D(b);break;case 2:null===a.b&&(a.b=b.c);w(b);break;case 3:A(b);break;case 4:z(b);break;case 5:var c=new jh;G(b,c,lh);a.a=a.a||[];a.a.push(c);break;case 1E3:y(b);break;default:x(b)}}jh.prototype.getExtension=function(){return null}; +function lh(a,b){for(;u(b);)switch(b.a){case 1:var c=C(b);a.a=a.a||[];a.a.push(c);break;case 2:null===a.b&&(a.b=b.c);w(b);break;default:x(b)}};function mh(){this.Oa=null}mh.prototype.getExtension=function(){return null};function nh(a,b){for(;u(b);)switch(b.a){case 1:var c=y(b);a.Oa=c;break;case 2:y(b);break;case 3:y(b);break;case 4:y(b);break;default:x(b)}};function oh(){this.a=this.c=this.f=this.b=null}function ph(){this.a=this.w=this.C=this.j=this.m=this.u=this.c=this.A=this.i=this.l=this.s=this.b=this.f=this.v=this.D=this.B=this.g=this.o=this.h=null}function qh(){this.b=this.c=this.a=null}function rh(){}function sh(){this.c=this.a=this.f=this.g=this.b=null}function th(){this.a=this.b=null}function uh(){this.g=this.b=this.f=this.a=this.c=null}function vh(){this.a=null}function wh(){this.a=null}function xh(){this.a=null}function yh(){} +function zh(){this.Ra=this.a=this.Sa=this.Ka=this.Na=null}function Ah(){this.a=null}function Bh(){}function Ch(){this.a=this.b=null}function Dh(){this.a=null}function Eh(){}function Fh(){this.a=null}function Gh(){this.a=null}function Hh(){this.a=null}function Ih(){this.a=null}function Jh(){this.a=null}function Kh(){this.a=null}function Lh(){}function Mh(){this.h=this.j=this.b=this.a=this.i=this.c=this.l=this.f=this.g=null}var Nh=[]; +oh.prototype.getExtension=function(a){var b=!1;25E6<=a&&536870912>a&&(b=!0);return b?P(this.a,a):null}; +function Oh(a,b){for(;u(b);)switch(b.a){case 1:null===a.b&&(a.b=b.c);w(b);break;case 2:null===a.f&&(a.f=b.c);w(b);break;case 3:y(b);break;case 4:y(b);break;case 5:t(b.b);break;case 6:C(b);break;case 7:y(b);break;case 8:C(b);break;case 9:B(b);break;case 10:y(b);break;case 11:E(b);break;case 12:null===a.c&&(a.c=b.c);w(b);break;case 13:y(b);break;case 14:y(b);break;case 15:C(b);break;case 1001:y(b);break;case 1E3:x(b);break;default:a.a=a.a||[];var c=Q(b,Nh);a.a.push(c)}}ph.prototype.getExtension=function(){return null}; +function Ph(a,b){for(a.a=b.b.b;u(b);)switch(b.a){case 1:null===a.h&&(a.h=b.c);w(b);a.o=b.b.a;break;case 2:null===a.g&&(a.g=b.c);w(b);a.B=b.b.a;break;case 3:null===a.D&&(a.D=b.c);w(b);break;case 4:null===a.v&&(a.v=b.c);w(b);break;case 5:y(b);break;case 6:var c=y(b);a.f=c;break;case 7:y(b);break;case 8:null===a.b&&(a.b=b.c);w(b);a.s=b.b.a;break;case 9:null===a.i&&(a.i=b.c);w(b);a.A=b.b.a;break;case 10:null===a.c&&(a.c=b.c);w(b);a.u=b.b.a;break;case 11:null===a.j&&(a.j=b.c);w(b);a.C=b.b.a;break;case 12:null=== +a.w&&(a.w=b.c);w(b);break;case 1E3:x(b);break;case 1001:x(b);break;case 1002:x(b);break;default:x(b)}}function Qh(a){return a.a&&null!=a.h&&null!=a.o?(a=Ic(a.a,a.h,a.o-a.h),a.S(),a.S(),a):Ic()}function Rh(a){return a.a&&null!=a.b&&null!=a.s?(a=Ic(a.a,a.b,a.s-a.b),a.S(),a.S(),a):Ic()}function Sh(a){null!=a.i&&null==a.l&&(a.l=bd(a.a,a.i,a.A));return a.l}function Th(a){return a.a&&null!=a.c&&null!=a.u?(a=Ic(a.a,a.c,a.u-a.c),a.S(),a.S(),a):Ic()} +function Uh(a){null!=a.j&&null==a.m&&(a.m=bd(a.a,a.j,a.C));return a.m}var U=[];qh.prototype.getExtension=function(a){var b=!1;25E6<=a&&536870912>a&&(b=!0);return b?P(this.b,a):null}; +function Vh(a,b){for(;u(b);)switch(b.a){case 1:var c=new ph;G(b,c,Ph);a.a=c;break;case 2:z(b);break;case 3:y(b);break;case 4:y(b);break;case 5:t(b.b);break;case 6:B(b);break;case 7:c=z(b);a.c=c;break;case 8:E(b);break;case 10:D(b);break;case 11:y(b);break;case 12:y(b);break;case 13:C(b);break;case 1E3:y(b);break;default:a.b=a.b||[],c=Q(b,U),a.b.push(c)}}function Wh(a){null===a.a&&(a.a=new ph);return a.a}rh.prototype.getExtension=function(){return null}; +function Xh(a,b){for(;u(b);)switch(b.a){case 1:G(b,new ph,Ph);break;case 2:y(b);break;case 3:y(b);break;default:x(b)}}sh.prototype.getExtension=function(){return null}; +function Yh(a,b){for(;u(b);)switch(b.a){case 1:null===a.b&&(a.b=b.c);w(b);break;case 2:null===a.g&&(a.g=b.c);w(b);break;case 3:null===a.f&&(a.f=b.c);w(b);break;case 4:null===a.a&&(a.a=b.c);w(b);break;case 5:null===a.c&&(a.c=b.c);w(b);break;case 6:y(b);break;case 1E3:x(b);break;case 1001:x(b);break;case 1002:x(b);break;default:x(b)}}var Zh=[];th.prototype.getExtension=function(a){var b=!1;25E6<=a&&536870912>a&&(b=!0);return b?P(this.a,a):null}; +function $h(a,b){for(;u(b);)switch(b.a){case 1:var c=new rh;G(b,c,Xh);a.b=a.b||[];a.b.push(c);break;case 2:c=new sh;G(b,c,Yh);break;case 3:y(b);break;case 4:y(b);break;case 5:t(b.b);break;case 6:D(b);break;case 7:B(b);break;case 8:E(b);break;case 9:y(b);break;case 10:y(b);break;case 1E3:y(b);break;default:a.a=a.a||[],c=Q(b,Zh),a.a.push(c)}}var ai=[];uh.prototype.getExtension=function(a){var b=!1;25E6<=a&&536870912>a&&(b=!0);return b?P(this.b,a):null}; +function bi(a,b){for(a.g=b.b.b;u(b);)switch(b.a){case 1:null===a.a&&(a.a=b.c);w(b);a.f=b.b.a;break;case 2:B(b);break;case 3:y(b);break;case 4:y(b);break;case 5:t(b.b);break;case 6:E(b);break;case 1E3:y(b);break;default:a.b=a.b||[];var c=Q(b,ai);a.b.push(c)}}uh.prototype.getImageData=function(){null!=this.a&&null==this.c&&(this.c=cd(this.g,this.a,this.f));return this.c};vh.prototype.getExtension=function(){return null}; +function ci(a,b){for(;u(b);)switch(b.a){case 1:C(b);break;case 2:null===a.a&&(a.a=b.c);w(b);break;case 3:var c=new ph;G(b,c,Ph);break;case 4:y(b);break;case 5:y(b);break;default:x(b)}}var di=[];wh.prototype.getExtension=function(a){var b=!1;25E6<=a&&536870912>a&&(b=!0);return b?P(this.a,a):null}; +function ei(a,b){for(;u(b);)switch(b.a){case 1:G(b,new vh,ci);break;case 2:y(b);break;case 3:y(b);break;case 4:t(b.b);break;case 5:B(b);break;case 6:E(b);break;case 1E3:y(b);break;default:a.a=a.a||[];var c=Q(b,di);a.a.push(c)}}xh.prototype.getExtension=function(){return null};function fi(a,b){for(;u(b);)switch(b.a){case 1:C(b);break;case 2:null===a.a&&(a.a=b.c);w(b);break;case 3:y(b);break;case 4:y(b);break;default:x(b)}}yh.prototype.getExtension=function(){return null}; +function gi(a,b){for(;u(b);)switch(b.a){case 1:y(b);break;case 2:y(b);break;case 3:y(b);break;case 4:y(b);break;case 7:D(b);break;default:x(b)}}zh.prototype.getExtension=function(){return null};function hi(a,b){for(a.Ra=b.b.b;u(b);)switch(b.a){case 1:null===a.Ka&&(a.Ka=b.c);w(b);a.Sa=b.b.a;break;case 2:var c=new yh;G(b,c,gi);a.a=a.a||[];a.a.push(c);break;default:x(b)}}Ah.prototype.getExtension=function(){return null}; +function ii(a,b){for(;u(b);)switch(b.a){case 1:C(b);break;case 2:var c=C(b);a.a=c;break;default:x(b)}}Bh.prototype.getExtension=function(){return null};function ji(a,b){for(;u(b);)switch(b.a){case 1:y(b);break;case 2:y(b);break;case 3:y(b);break;default:x(b)}}Ch.prototype.getExtension=function(){return null};function ki(a,b){for(;u(b);)switch(b.a){case 1:A(b);break;case 2:null===a.b&&(a.b=b.c);w(b);break;case 3:var c=y(b);a.a=a.a||[];a.a.push(c);break;default:x(b)}}Dh.prototype.getExtension=function(){return null}; +function li(a,b){for(;u(b);)switch(b.a){case 1:var c=new Ch;G(b,c,ki);a.a=a.a||[];a.a.push(c);break;default:x(b)}}Eh.prototype.getExtension=function(){return null};function mi(a,b){for(;u(b);)x(b)}Fh.prototype.getExtension=function(){return null};function ni(a,b){for(;u(b);)switch(b.a){case 1:var c=new oh;G(b,c,Oh);a.a=a.a||[];a.a.push(c);break;case 2:c=new Bh;G(b,c,ji);break;default:x(b)}}Gh.prototype.getExtension=function(){return null}; +function oi(a,b){for(;u(b);)switch(b.a){case 1:var c=new qh;G(b,c,Vh);a.a=a.a||[];a.a.push(c);break;case 2:c=new Bh;G(b,c,ji);break;default:x(b)}}Hh.prototype.getExtension=function(){return null};function pi(a,b){for(;u(b);)switch(b.a){case 1:var c=new th;G(b,c,$h);a.a=a.a||[];a.a.push(c);break;case 2:c=new Bh;G(b,c,ji);break;default:x(b)}}Ih.prototype.getExtension=function(){return null}; +function qi(a,b){for(;u(b);)switch(b.a){case 1:var c=new $g;G(b,c,hh);a.a=a.a||[];a.a.push(c);break;case 2:c=new Bh;G(b,c,ji);break;default:x(b)}}Jh.prototype.getExtension=function(){return null};function ri(a,b){for(;u(b);)switch(b.a){case 1:var c=new uh;G(b,c,bi);a.a=a.a||[];a.a.push(c);break;default:x(b)}}Kh.prototype.getExtension=function(){return null}; +function si(a,b){for(;u(b);)switch(b.a){case 1:var c=new wh;G(b,c,ei);a.a=a.a||[];a.a.push(c);break;case 2:c=new Bh;G(b,c,ji);break;default:x(b)}}Lh.prototype.getExtension=function(){return null};function ti(a,b){for(;u(b);)switch(b.a){case 1:A(b);break;case 2:y(b);break;default:x(b)}} +function ui(a,b){for(;u(b);)switch(b.a){case 1:var c=new mh;G(b,c,nh);a.g=c;break;case 2:c=new Ah;G(b,c,ii);a.f=c;break;case 3:c=new ih;G(b,c,kh);a.l=a.l||[];a.l.push(c);break;case 4:c=new zh;G(b,c,hi);a.c=c;break;case 5:c=new xh;G(b,c,fi);a.i=a.i||[];a.i.push(c);break;case 6:c=new Eh;G(b,c,mi);break;case 7:c=new Fh;G(b,c,ni);break;case 8:c=new Gh;G(b,c,oi);a.a=c;break;case 9:c=new Hh;G(b,c,pi);break;case 10:c=new Ih;G(b,c,qi);break;case 11:c=new Jh;G(b,c,ri);a.b=c;break;case 12:c=new Kh;G(b,c,si); +break;case 13:c=new Dh;G(b,c,li);break;case 14:y(b);break;case 15:c=new Lh;G(b,c,ti);a.j=a.j||[];a.j.push(c);break;case 16:B(b);break;default:a.h=a.h||[],c=Q(b,vi),a.h.push(c)}}var vi=[];Mh.prototype.getExtension=function(a){var b=!1;25E6<=a&&536870912>a&&(b=!0);return b?P(this.h,a):null};function wi(a){null===a.f&&(a.f=new Ah);return a.f}function xi(a){null===a.a&&(a.a=new Gh);return a.a};function yi(){this.b=this.a=null}function zi(){this.b=this.a=null}yi.prototype.getExtension=function(){return null};zi.prototype.getExtension=function(){return null};function Ai(a,b){for(;u(b);)switch(b.a){case 1:var c=D(b);a.a=c;break;case 2:c=D(b);a.b=c;break;default:x(b)}};function Bi(){this.a=this.f=this.b=this.g=this.c=null}Bi.prototype.getExtension=function(){return null};function Ci(){this.c=this.b=this.a=null}Ci.prototype.getExtension=function(){return null};function Di(){this.a=this.f=this.h=this.c=this.b=this.g=null}Di.prototype.getExtension=function(){return null};function Ei(){this.c=this.a=this.g=this.f=this.b=null}function Fi(a){var b=new Ei;Gi(b);b.b=a.b;b.f=a.f;b.g=a.g;b.a=a.a;b.c=a.c;return b}function Gi(a){a.b=null;a.f=null;a.g=null;a.a=null;a.c=null}Ei.prototype.getExtension=function(){return null};function Hi(a,b){for(;u(b);)switch(b.a){case 1:var c=y(b);a.b=c;break;case 2:c=y(b);a.f=c;break;case 3:c=y(b);a.g=c;break;case 4:c=C(b);a.a=c;break;case 5:c=A(b);a.c=c;break;default:x(b)}} +function Ii(a,b){return a===b?!0:null===a||null===b?!1:a.b!==b.b||a.f!==b.f||a.g!==b.g||a.a!==b.a||a.c!==b.c?!1:!0};function Ji(){this.b=this.a=null}function Ki(){}Ji.prototype.getExtension=function(){return null};Ki.prototype.getExtension=function(){return null};function Li(a,b){for(;u(b);)x(b)};function Mi(){this.b=this.a=null}function Ni(a){if(a.a)for(var b=0;b<a.a.length;b++){var c=a.a[b];c&&ig(c)}a.a=null;a.b=null}Mi.prototype.getExtension=function(){return null};function Oi(a,b){for(;u(b);)switch(b.a){case 1:var c=new ag;G(b,c,kg);a.a=a.a||[];a.a.push(c);break;case 2:c=z(b);a.b=c;break;default:x(b)}};function Pi(){this.u=this.f=this.g=this.v=this.c=this.I=this.J=this.T=this.P=this.s=this.H=this.R=this.l=this.j=this.M=this.N=this.m=this.h=this.K=this.L=this.A=this.B=this.C=this.i=this.F=this.D=this.G=this.b=this.a=this.O=this.w=this.o=null} +function Qi(a,b){Ri(a);a.o=b.o;a.w=b.w;a.O=b.O;a.a=b.a;a.b=b.b;a.G=b.G;a.D=b.D;a.F=b.F;a.i=b.i;a.C=b.C;a.B=b.B;a.A=b.A;a.L=b.L;a.K=b.K;a.h=b.h;a.m=b.m;a.N=b.N;a.M=b.M;a.j=b.j;a.l=b.l;a.R=b.R;a.H=b.H;a.s=b.s;a.P=b.P;a.T=b.T;a.J=b.J;a.I=b.I;a.c=b.c;a.v=b.v;a.g=b.g;a.f=b.f;a.u=b.u} +function Ri(a){a.o=null;a.w=null;a.O=null;a.a=null;a.b=null;a.G=null;a.D=null;a.F=null;a.i=null;a.C=null;a.B=null;a.A=null;a.L=null;a.K=null;a.h=null;a.m=null;a.N=null;a.M=null;a.j=null;a.l=null;a.R=null;a.H=null;a.s=null;a.P=null;a.T=null;a.J=null;a.I=null;a.c=null;a.v=null;a.g=null;a.f=null;a.u=null}Pi.prototype.getExtension=function(){return null}; +function Si(a,b){for(;u(b);)switch(b.a){case 1:var c=z(b);a.o=c;break;case 2:c=y(b);a.w=c;break;case 3:c=y(b);a.O=c;break;case 4:c=z(b);a.a=c;break;case 7:c=y(b);a.b=c;break;case 9:c=A(b);a.G=c;break;case 17:c=z(b);a.D=c;break;case 18:c=z(b);a.F=c;break;case 20:c=y(b);a.i=c;break;case 23:c=z(b);a.C=c;break;case 24:c=y(b);a.B=c;break;case 25:c=z(b);a.A=c;break;case 26:c=y(b);a.L=c;break;case 27:c=y(b);a.K=c;break;case 28:c=Nc(b.b);a.h=c;break;case 29:c=z(b);a.m=c;break;case 32:c=y(b);a.N=c;break;case 33:c= +y(b);a.M=c;break;case 39:c=y(b);a.j=c;break;case 40:c=y(b);a.l=c;break;case 41:c=y(b);a.R=c;break;case 42:c=z(b);a.H=c;break;case 43:c=y(b);a.s=c;break;case 44:c=z(b);a.P=c;break;case 45:c=z(b);a.T=c;break;case 46:c=y(b);a.J=c;break;case 47:c=y(b);a.I=c;break;case 48:c=z(b);a.c=c;break;case 49:c=z(b);a.v=c;break;case 50:c=z(b);a.g=c;break;case 51:c=z(b);a.f=c;break;case 52:c=A(b);a.u=c;break;default:x(b)}};function Ti(){this.a=this.b=this.c=this.f=null}function Ui(a){a.f=null;a.c=null;a.b=null;a.a=null}Ti.prototype.getExtension=function(){return null};function Vi(a,b){for(;u(b);)switch(b.a){case 1:var c=A(b);a.f=c;break;case 2:c=Mc(b.b);a.c=c;break;case 3:c=A(b);a.b=c;break;case 4:c=A(b);a.a=c;break;default:x(b)}};function Wi(){this.f=this.a=this.g=this.s=this.h=this.v=this.i=this.o=this.b=this.m=this.l=this.j=this.c=this.u=this.w=null}function Xi(){this.g=this.f=this.c=this.a=this.b=null}function Yi(){this.a=this.b=null}function Zi(){this.b=this.c=this.a=null}function $i(){this.N=this.u=this.H=this.O=this.M=this.a=this.C=this.G=this.J=this.R=this.w=this.B=this.A=this.l=this.i=this.f=this.F=this.g=this.D=this.K=this.L=this.h=this.P=this.v=this.I=this.s=this.c=this.o=this.m=this.b=this.j=null} +function aj(){this.a=null}function bj(){this.l=this.h=this.b=this.j=this.i=this.a=this.f=this.c=this.g=null}function cj(){this.f=this.j=this.a=this.i=this.c=this.b=this.g=this.h=null}function dj(){this.c=this.b=this.f=this.a=null}function ej(){this.h=this.c=this.a=this.g=this.f=this.b=this.o=this.i=this.j=this.l=this.m=null}function fj(){this.a=null}function gj(){this.a=this.b=null}function hj(){this.a=this.b=null}function ij(){this.l=this.f=this.i=this.g=this.a=this.h=this.j=this.c=this.b=null} +function jj(){this.a=null}function kj(){this.b=this.a=null}function lj(){this.g=this.a=this.b=this.f=this.h=this.c=null}function mj(a){var b=new Wi;nj(b);b.w=a.w;b.u=a.u;b.c=a.c?bg(a.c):null;b.j=a.j;b.l=a.l;b.m=a.m;if(a.b){var c=new Ti;var d=a.b;Ui(c);c.f=d.f;c.c=d.c;c.b=d.b;c.a=d.a}else c=null;b.b=c;b.o=a.o;b.i=a.i;b.v=a.v;b.h=a.h;b.s=a.s;b.g=a.g;if(a.a){d=a.a;c=new jj;oj(c);if(d.a){d=d.a;var e=new kj;pj(e);e.a=d.a?mj(d.a):null;e.b=d.b;d=e}else d=null;c.a=d}else c=null;b.a=c;b.f=a.f;return b} +function nj(a){a.w=null;a.u=null;var b=a.c;b&&cg(b);a.c=null;a.j=null;a.l=null;a.m=null;(b=a.b)&&Ui(b);a.b=null;a.o=null;a.i=null;a.v=null;a.h=null;a.s=null;a.g=null;(b=a.a)&&oj(b);a.a=null;a.f=null}Wi.prototype.getExtension=function(){return null};function qj(a){return null===a?null:mj(a)} +function rj(a,b){for(;u(b);)switch(b.a){case 1:var c=A(b);a.w=c;break;case 2:c=A(b);a.u=c;break;case 3:c=new Zf;G(b,c,dg);a.c=c;break;case 4:c=A(b);a.j=c;break;case 5:c=C(b);a.l=c;break;case 6:c=C(b);a.m=c;break;case 7:c=new Ti;G(b,c,Vi);a.b=c;break;case 8:c=A(b);a.o=c;break;case 9:c=z(b);a.i=c;break;case 11:c=z(b);a.v=c;break;case 12:c=A(b);a.h=c;break;case 13:c=A(b);a.s=c;break;case 14:c=A(b);a.g=c;break;case 16:c=new jj;G(b,c,sj);a.a=c;break;case 17:c=y(b);a.f=c;break;default:x(b)}} +function tj(a,b){if(a===b)a=!0;else if(null===a||null===b)a=!1;else{var c;if(c=a.w===b.w&&a.u===b.u&&eg(a.c,b.c)&&a.j===b.j&&a.l===b.l&&a.m===b.m){c=a.b;var d=b.b;c=c===d?!0:null===c||null===d?!1:c.f!==d.f||c.c!==d.c||c.b!==d.b||c.a!==d.a?!1:!0}if(c=c&&a.o===b.o&&a.i===b.i&&a.v===b.v&&a.h===b.h&&a.s===b.s&&a.g===b.g)d=a.a,c=b.a,d===c?c=!0:null===d||null===c?c=!1:(d=d.a,c=c.a,c=d===c||(null===d||null===c?0:tj(d.a,c.a)&&d.b===c.b)?!0:!1);a=c&&a.f===b.f?!0:!1}return a} +function uj(a){a.b=null;var b=a.a;b&&cg(b);a.a=null;a.c=null;a.f=null;a.g=null}Xi.prototype.getExtension=function(){return null};function vj(a){if(null===a)a=null;else{var b=new Xi;uj(b);b.b=a.b;b.a=a.a?bg(a.a):null;b.c=a.c;b.f=a.f;b.g=a.g;a=b}return a}function wj(a,b){for(;u(b);)switch(b.a){case 1:var c=y(b);a.b=c;break;case 2:c=new Zf;G(b,c,dg);a.a=c;break;case 3:c=A(b);a.c=c;break;case 4:c=Mc(b.b);a.f=c;break;case 5:c=z(b);a.g=c;break;default:x(b)}} +function xj(a,b){return a===b?!0:null===a||null===b?!1:a.b===b.b&&eg(a.a,b.a)&&a.c===b.c&&a.f===b.f&&a.g===b.g?!0:!1}function yj(a,b){a.b=null;a.a=null;a.b=b.b;a.a=b.a}Yi.prototype.getExtension=function(){return null};function zj(a,b){for(;u(b);)switch(b.a){case 1:var c=C(b);a.b=c;break;case 2:c=z(b);a.a=c;break;default:x(b)}}function Aj(a,b){a.a=null;a.c=null;a.b=null;a.a=b.a;a.c=b.c;a.b=b.b}Zi.prototype.getExtension=function(){return null}; +function Bj(a,b){for(;u(b);)switch(b.a){case 1:var c=C(b);a.a=c;break;case 2:c=C(b);a.c=c;break;case 3:c=E(b);a.b=c;break;default:x(b)}} +function Cj(a,b){Dj(a);if(b.j){var c=b.j;var d=new ej;Ej(d);d.m=c.m;d.l=c.l;d.j=c.j;d.i=c.i;d.o=c.o;d.b=I(c.b);d.f=c.f;d.g=c.g;d.a=J(c.a,Fj);if(c.c){var e=c.c;var f=new gj;Gj(f);f.b=e.b;f.a=e.a?Hj(e.a):null;e=f}else e=null;d.c=e;d.h=c.h;c=d}else c=null;a.j=c;b.b?(c=b.b,d=new ij,Ij(d),d.b=c.b,d.c=c.c,d.j=c.j,d.h=c.h,c.a?(e=new bj,Jj(e,c.a)):e=null,d.a=e,d.g=c.g,d.i=c.i,d.f=c.f,d.l=c.l,c=d):c=null;a.b=c;a.m=b.m;a.o=b.o;b.c?(c=new Pi,Qi(c,b.c)):c=null;a.c=c;a.s=b.s;a.I=b.I;a.v=b.v;a.P=b.P;b.h?(c=new Yi, +yj(c,b.h)):c=null;a.h=c;a.L=b.L;a.K=b.K;a.D=b.D;a.g=I(b.g);a.F=b.F;b.f?(c=b.f,d=new dj,Kj(d),d.a=I(c.a),d.f=c.f,d.b=I(c.b),d.c=c.c,c=d):c=null;a.f=c;b.i?(c=new Zi,Aj(c,b.i)):c=null;a.i=c;b.l?(c=b.l,d=new cj,Lj(d),d.h=c.h,d.g=c.g,d.b=c.b,d.c=c.c,d.i=c.i,d.a=c.a,d.j=c.j,d.f=c.f,c=d):c=null;a.l=c;a.A=b.A;a.B=b.B;a.w=b.w;a.R=b.R;a.J=b.J;a.G=b.G;a.C=b.C;a.a=J(b.a,Mj);a.M=b.M;a.O=b.O;a.H=b.H;a.u=b.u;a.N=b.N} +function Dj(a){var b=a.j;b&&Ej(b);a.j=null;(b=a.b)&&Ij(b);a.b=null;a.m=null;a.o=null;(b=a.c)&&Ri(b);a.c=null;a.s=null;a.I=null;a.v=null;a.P=null;if(b=a.h)b.b=null,b.a=null;a.h=null;a.L=null;a.K=null;a.D=null;a.g=null;a.F=null;(b=a.f)&&Kj(b);a.f=null;if(b=a.i)b.a=null,b.c=null,b.b=null;a.i=null;(b=a.l)&&Lj(b);a.l=null;a.A=null;a.B=null;a.w=null;a.R=null;a.J=null;a.G=null;a.C=null;if(a.a)for(b=0;b<a.a.length;b++){var c=a.a[b];c&&(c.a=null)}a.a=null;a.M=null;a.O=null;a.H=null;a.u=null;a.N=null} +$i.prototype.getExtension=function(){return null}; +function Nj(a,b){for(;u(b);)switch(b.a){case 1:var c=new ej;G(b,c,Oj);a.j=c;break;case 2:c=new ij;G(b,c,Pj);a.b=c;break;case 3:c=z(b);a.m=c;break;case 4:c=z(b);a.o=c;break;case 6:c=new Pi;G(b,c,Si);a.c=c;break;case 7:c=z(b);a.s=c;break;case 8:c=z(b);a.I=c;break;case 9:c=C(b);a.v=c;break;case 10:c=z(b);a.P=c;break;case 11:c=new Yi;G(b,c,zj);a.h=c;break;case 12:c=z(b);a.L=c;break;case 13:c=z(b);a.K=c;break;case 14:c=z(b);a.D=c;break;case 15:c=y(b);a.g=a.g||[];a.g.push(c);break;case 16:c=z(b);a.F=c; +break;case 17:c=new dj;G(b,c,Qj);a.f=c;break;case 19:c=new Zi;G(b,c,Bj);a.i=c;break;case 20:c=new cj;G(b,c,Rj);a.l=c;break;case 25:c=z(b);a.A=c;break;case 26:c=z(b);a.B=c;break;case 31:c=z(b);a.w=c;break;case 33:c=z(b);a.R=c;break;case 34:c=z(b);a.J=c;break;case 35:c=z(b);a.G=c;break;case 37:c=z(b);a.C=c;break;case 38:c=new aj;G(b,c,Sj);a.a=a.a||[];a.a.push(c);break;case 39:c=z(b);a.M=c;break;case 40:c=z(b);a.O=c;break;case 41:c=z(b);a.H=c;break;case 42:c=z(b);a.u=c;break;case 43:c=y(b);a.N=c;break; +default:x(b)}}aj.prototype.getExtension=function(){return null};function Mj(a){if(null===a)a=null;else{var b=new aj;b.a=null;b.a=a.a;a=b}return a}function Sj(a,b){for(;u(b);)switch(b.a){case 1:a.a=y(b);break;default:x(b)}}function Tj(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a?!1:!0}function Jj(a,b){Uj(a);a.g=b.g;a.c=b.c;a.f=b.f;a.a=b.a;a.i=b.i;a.j=b.j;a.b=b.b;a.h=b.h;a.l=b.l}function Uj(a){a.g=null;a.c=null;a.f=null;a.a=null;a.i=null;a.j=null;a.b=null;a.h=null} +bj.prototype.getExtension=function(){return null};function Vj(a,b){for(a.l=b.b.b;u(b);)switch(b.a){case 2:var c=z(b);a.g=c;break;case 3:c=z(b);a.c=c;break;case 4:c=z(b);a.f=c;break;case 5:c=z(b);a.a=c;break;case 6:c=C(b);a.i=c;break;case 7:c=C(b);a.j=c;break;case 9:c=z(b);a.b=c;break;case 10:c=C(b);a.h=c;break;default:x(b)}}function Lj(a){a.h=null;a.g=null;a.b=null;a.c=null;a.i=null;a.a=null;a.j=null;a.f=null}cj.prototype.getExtension=function(){return null}; +function Rj(a,b){for(;u(b);)switch(b.a){case 1:var c=C(b);a.h=c;break;case 2:c=C(b);a.g=c;break;case 3:c=z(b);a.b=c;break;case 4:c=z(b);a.c=c;break;case 5:c=C(b);a.i=c;break;case 6:c=z(b);a.a=c;break;case 7:c=z(b);a.j=c;break;case 8:c=z(b);a.f=c;break;default:x(b)}}function Kj(a){a.a=null;a.f=null;a.b=null;a.c=null}dj.prototype.getExtension=function(){return null}; +function Qj(a,b){for(;u(b);)switch(b.a){case 1:var c=C(b);a.a=a.a||[];a.a.push(c);break;case 2:c=z(b);a.f=c;break;case 3:c=C(b);a.b=a.b||[];a.b.push(c);break;case 4:c=C(b);a.c=c;break;default:x(b)}}function Ej(a){a.m=null;a.l=null;a.j=null;a.i=null;a.o=null;a.b=null;a.f=null;a.g=null;if(a.a)for(var b=0;b<a.a.length;b++){var c=a.a[b];c&&(c.a=null)}a.a=null;(b=a.c)&&Gj(b);a.c=null;a.h=null}ej.prototype.getExtension=function(){return null}; +function Oj(a,b){for(;u(b);)switch(b.a){case 1:var c=C(b);a.m=c;break;case 2:c=C(b);a.l=c;break;case 3:c=E(b);a.j=c;break;case 5:c=C(b);a.i=c;break;case 6:c=z(b);a.o=c;break;case 7:c=C(b);a.b=a.b||[];a.b.push(c);break;case 8:c=C(b);a.f=c;break;case 9:c=z(b);a.g=c;break;case 10:c=new fj;G(b,c,Wj);a.a=a.a||[];a.a.push(c);break;case 11:c=new gj;G(b,c,Xj);a.c=c;break;case 12:c=C(b);a.h=c;break;default:x(b)}} +function Yj(a,b){if(a===b)a=!0;else if(null===a||null===b)a=!1;else{var c;if(c=a.m===b.m&&a.l===b.l&&a.j===b.j&&a.i===b.i&&a.o===b.o&&L(a.b,b.b)&&a.f===b.f&&a.g===b.g&&M(a.a,b.a,Zj)){var d=a.c;c=b.c;if(d===c)c=!0;else if(null===d||null===c)c=!1;else{var e;if(e=d.b===c.b)d=d.a,c=c.a,e=d===c?!0:null===d||null===c?!1:d.b!==c.b||d.a!==c.a?!1:!0;c=e?!0:!1}}a=c&&a.h===b.h?!0:!1}return a}fj.prototype.getExtension=function(){return null}; +function Fj(a){if(null===a)a=null;else{var b=new fj;b.a=null;b.a=a.a;a=b}return a}function Wj(a,b){for(;u(b);)switch(b.a){case 1:a.a=C(b);break;default:x(b)}}function Zj(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a?!1:!0}function Gj(a){a.b=null;var b=a.a;b&&(b.b=null,b.a=null);a.a=null}gj.prototype.getExtension=function(){return null};function Xj(a,b){for(;u(b);)switch(b.a){case 1:var c=C(b);a.b=c;break;case 3:c=new hj;G(b,c,ak);a.a=c;break;default:x(b)}} +function Hj(a){var b=new hj;b.b=null;b.a=null;b.b=a.b;b.a=a.a;return b}hj.prototype.getExtension=function(){return null};function ak(a,b){for(;u(b);)switch(b.a){case 1:var c=y(b);a.b=c;break;case 2:c=y(b);a.a=c;break;default:x(b)}}function Ij(a){a.b=null;a.c=null;a.j=null;a.h=null;var b=a.a;b&&Uj(b);a.a=null;a.g=null;a.i=null;a.f=null;a.l=null}ij.prototype.getExtension=function(){return null}; +function Pj(a,b){for(;u(b);)switch(b.a){case 1:var c=z(b);a.b=c;break;case 2:c=z(b);a.c=c;break;case 3:c=z(b);a.j=c;break;case 4:c=z(b);a.h=c;break;case 5:c=new bj;G(b,c,Vj);a.a=c;break;case 6:c=z(b);a.g=c;break;case 7:c=z(b);a.i=c;break;case 8:c=z(b);a.f=c;break;case 20:c=C(b);a.l=c;break;default:x(b)}} +function bk(a,b){if(a===b)a=!0;else if(null===a||null===b)a=!1;else{var c;if(c=a.b===b.b&&a.c===b.c&&a.j===b.j&&a.h===b.h){c=a.a;var d=b.a;c=c===d?!0:null===c||null===d?!1:c.g!==d.g||c.c!==d.c||c.f!==d.f||c.a!==d.a||c.i!==d.i||c.j!==d.j||c.b!==d.b||c.h!==d.h?!1:!0}a=c&&a.g===b.g&&a.i===b.i&&a.f===b.f&&a.l===b.l?!0:!1}return a}function oj(a){var b=a.a;b&&pj(b);a.a=null}jj.prototype.getExtension=function(){return null}; +function sj(a,b){for(;u(b);)switch(b.a){case 1:var c=new kj;G(b,c,ck);a.a=c;break;default:x(b)}}function pj(a){var b=a.a;b&&nj(b);a.a=null;a.b=null}kj.prototype.getExtension=function(){return null};function ck(a,b){for(;u(b);)switch(b.a){case 1:var c=new Wi;G(b,c,rj);a.a=c;break;case 2:c=z(b);a.b=c;break;default:x(b)}}function dk(a){a.c=null;a.h=null;a.f=null;a.b=null;a.a=null;a.g=null}lj.prototype.getExtension=function(){return null}; +function ek(a,b){for(;u(b);)switch(b.a){case 1:var c=C(b);a.c=c;break;case 2:c=z(b);a.h=c;break;case 3:c=z(b);a.f=c;break;case 4:c=y(b);a.b=a.b||[];a.b.push(c);break;case 5:c=y(b);a.a=a.a||[];a.a.push(c);break;case 6:c=z(b);a.g=c;break;default:x(b)}};function fk(){this.b=this.a=null}function gk(a){var b=a.a;b&&Rd(b);a.a=null;(b=a.b)&&Rd(b);a.b=null}fk.prototype.getExtension=function(){return null};function hk(a){if(null===a)a=null;else{var b=new fk;gk(b);b.a=a.a?Qd(a.a):null;b.b=a.b?Qd(a.b):null;a=b}return a}function ik(a,b){for(;u(b);)switch(b.a){case 1:var c=new Ld;G(b,c,Sd);a.a=c;break;case 2:c=new Ld;G(b,c,Sd);a.b=c;break;default:x(b)}}function jk(a,b){return a===b?!0:null===a||null===b?!1:Td(a.a,b.a)&&Td(a.b,b.b)?!0:!1};function kk(){this.a=this.c=this.b=null}kk.prototype.getExtension=function(){return null};function lk(a,b){for(;u(b);)switch(b.a){case 1:var c=z(b);a.b=c;break;case 2:c=A(b);a.c=c;break;case 3:c=A(b);a.a=c;break;default:x(b)}};function mk(){this.B=this.s=this.m=this.i=this.f=this.D=this.b=this.G=this.h=this.l=this.H=this.g=this.j=this.v=this.a=this.A=this.w=this.o=this.c=this.u=this.F=this.C=null} +function nk(a,b){ok(a);a.C=b.C;a.F=b.F;a.u=b.u;a.c=b.c?yf(b.c):null;a.o=b.o;a.w=b.w;a.A=b.A;a.a=J(b.a,Lf);a.v=b.v;a.j=b.j;if(b.g){var c=new Zd;Ae(c,b.g)}else c=null;a.g=c;a.H=b.H;a.l=b.l;if(b.h){c=new kk;var d=b.h;c.b=null;c.c=null;c.a=null;c.b=d.b;c.c=d.c;c.a=d.a}else c=null;a.h=c;a.G=b.G;a.b=J(b.b,hk);a.D=b.D;a.f=I(b.f);b.i?(c=new Xd,d=b.i,c.a=null,c.a=d.a):c=null;a.i=c;a.m=b.m;a.s=b.s;a.B=b.B} +function ok(a){a.C=null;a.F=null;a.u=null;var b=a.c;b&&zf(b);a.c=null;a.o=null;a.w=null;a.A=null;if(a.a)for(b=0;b<a.a.length;b++){var c=a.a[b];c&&Jf(c)}a.a=null;a.v=null;a.j=null;(b=a.g)&&Be(b);a.g=null;a.H=null;a.l=null;if(b=a.h)b.b=null,b.c=null,b.a=null;a.h=null;a.G=null;if(a.b)for(b=0;b<a.b.length;b++)(c=a.b[b])&&gk(c);a.b=null;a.D=null;a.f=null;if(b=a.i)b.a=null;a.i=null;a.m=null;a.s=null;a.B=null}mk.prototype.getExtension=function(){return null}; +function pk(a,b){for(;u(b);)switch(b.a){case 1:var c=A(b);a.C=c;break;case 2:c=A(b);a.F=c;break;case 3:c=z(b);a.u=c;break;case 4:c=new xf;G(b,c,Af);a.c=c;break;case 5:c=A(b);a.o=c;break;case 6:c=A(b);a.w=c;break;case 7:c=C(b);a.A=c;break;case 8:c=new If;G(b,c,Mf);a.a=a.a||[];a.a.push(c);break;case 9:c=A(b);a.v=c;break;case 10:c=A(b);a.j=c;break;case 11:c=new Zd;G(b,c,Ze);a.g=c;break;case 12:c=C(b);a.H=c;break;case 13:c=C(b);a.l=c;break;case 14:c=new kk;G(b,c,lk);a.h=c;break;case 15:c=y(b);a.G=c;break; +case 16:c=new fk;G(b,c,ik);a.b=a.b||[];a.b.push(c);break;case 17:c=A(b);a.D=c;break;case 18:c=C(b);a.f=a.f||[];a.f.push(c);break;case 19:c=new Xd;G(b,c,Yd);a.i=c;break;case 20:c=z(b);a.m=c;break;case 21:c=z(b);a.s=c;break;case 22:c=z(b);a.B=c;break;default:x(b)}};function qk(){this.h=this.i=this.f=this.b=this.g=this.s=this.o=this.m=this.l=this.c=this.a=this.j=null}function rk(a){a.j=null;a.a=null;a.c=null;a.l=null;a.m=null;a.o=null;a.s=null;a.g=null;a.b=null;a.f=null;a.i=null;a.h=null}qk.prototype.getExtension=function(){return null}; +function sk(a,b){for(;u(b);)switch(b.a){case 1:var c=A(b);a.j=c;break;case 2:c=A(b);a.a=c;break;case 3:c=A(b);a.c=c;break;case 4:c=A(b);a.l=c;break;case 5:c=A(b);a.m=c;break;case 6:c=A(b);a.o=c;break;case 7:c=A(b);a.s=c;break;case 8:c=A(b);a.g=c;break;case 10:c=A(b);a.b=c;break;case 11:c=A(b);a.f=c;break;case 12:c=A(b);a.i=c;break;case 13:c=A(b);a.h=c;break;default:x(b)}};function tk(){this.a=null}function uk(a){a.a=null}tk.prototype.getExtension=function(){return null};function vk(a,b){for(;u(b);)switch(b.a){case 1:a.a=C(b);break;default:x(b)}};function wk(){this.M=this.L=this.s=this.i=this.K=this.D=this.h=this.H=this.o=this.u=this.C=this.G=this.B=this.c=this.m=this.A=this.I=this.f=this.F=this.v=this.a=this.j=this.w=this.g=this.J=this.l=this.b=null}function xk(){this.a=null} +function yk(a){var b=new wk;zk(b);b.b=J(a.b,qj);b.l=a.l?Sf(a.l):null;b.J=a.J;if(a.g){var c=new $i;Cj(c,a.g)}else c=null;b.g=c;b.w=a.w;if(a.j){c=new lj;var d=a.j;dk(c);c.c=d.c;c.h=d.h;c.f=d.f;c.b=I(d.b);c.a=I(d.a);c.g=d.g}else c=null;b.j=c;b.a=J(a.a,vj);b.v=a.v;b.F=a.F;a.f?(c=new mk,nk(c,a.f)):c=null;b.f=c;b.I=a.I;b.A=a.A;a.m?(c=a.m,d=new xk,d.a=null,d.a=c.a,c=d):c=null;b.m=c;a.c?(c=new Mi,d=a.c,Ni(c),c.a=J(d.a,jg),c.b=d.b):c=null;b.c=c;b.B=a.B;b.G=a.G;b.C=a.C;b.u=a.u;a.o?(c=new tk,d=a.o,uk(c),c.a= +d.a):c=null;b.o=c;b.H=a.H;a.h?(c=new qk,d=a.h,rk(c),c.j=d.j,c.a=d.a,c.c=d.c,c.l=d.l,c.m=d.m,c.o=d.o,c.s=d.s,c.g=d.g,c.b=d.b,c.f=d.f,c.i=d.i,c.h=d.h):c=null;b.h=c;b.D=a.D;b.K=a.K;b.i=a.i?new Uint8Array(a.i):null;b.s=a.s;b.L=a.L;b.M=a.M;return b} +function zk(a){if(a.b)for(var b=0;b<a.b.length;b++){var c=a.b[b];c&&nj(c)}a.b=null;(b=a.l)&&Tf(b);a.l=null;a.J=null;(b=a.g)&&Dj(b);a.g=null;a.w=null;(b=a.j)&&dk(b);a.j=null;if(a.a)for(b=0;b<a.a.length;b++)(c=a.a[b])&&uj(c);a.a=null;a.v=null;a.F=null;(b=a.f)&&ok(b);a.f=null;a.I=null;a.A=null;if(b=a.m)b.a=null;a.m=null;(b=a.c)&&Ni(b);a.c=null;a.B=null;a.G=null;a.C=null;a.u=null;(b=a.o)&&uk(b);a.o=null;a.H=null;(b=a.h)&&rk(b);a.h=null;a.D=null;a.K=null;a.i=null;a.s=null;a.L=null} +wk.prototype.getExtension=function(){return null}; +function Ak(a,b){for(a.M=b.b.b;u(b);)switch(b.a){case 1:var c=new Wi;G(b,c,rj);a.b=a.b||[];a.b.push(c);break;case 3:c=new Of;G(b,c,Uf);a.l=c;break;case 4:c=y(b);a.J=c;break;case 6:c=new $i;G(b,c,Nj);a.g=c;break;case 7:c=C(b);a.w=c;break;case 8:c=new lj;G(b,c,ek);a.j=c;break;case 9:c=new Xi;G(b,c,wj);a.a=a.a||[];a.a.push(c);break;case 12:c=z(b);a.v=c;break;case 13:c=A(b);a.F=c;break;case 15:c=new mk;G(b,c,pk);a.f=c;break;case 16:c=z(b);a.I=c;break;case 17:c=z(b);a.A=c;break;case 19:c=new xk;G(b,c, +Bk);a.m=c;break;case 20:c=new Mi;G(b,c,Oi);a.c=c;break;case 21:c=A(b);a.B=c;break;case 22:c=z(b);a.G=c;break;case 23:c=y(b);a.C=c;break;case 25:c=z(b);a.u=c;break;case 26:c=new tk;G(b,c,vk);a.o=c;break;case 27:c=z(b);a.H=c;break;case 28:c=new qk;G(b,c,sk);a.h=c;break;case 29:c=C(b);a.D=c;break;case 30:c=C(b);a.K=c;break;case 31:null===a.s&&(a.s=b.c);w(b);a.L=b.b.a;break;default:x(b)}} +function Ck(a,b){if(a===b)a=!0;else if(null===a||null===b)a=!1;else{var c;if(c=M(a.b,b.b,tj)&&Yf(a.l,b.l)&&a.J===b.J){c=a.g;var d=b.g;if(c===d)c=!0;else if(null===c||null===d)c=!1;else{var e;if(e=Yj(c.j,d.j)&&bk(c.b,d.b)&&c.m===d.m&&c.o===d.o){e=c.c;var f=d.c;e=e===f?!0:null===e||null===f?!1:e.o!==f.o||e.w!==f.w||e.O!==f.O||e.a!==f.a||e.b!==f.b||e.G!==f.G||e.D!==f.D||e.F!==f.F||e.i!==f.i||e.C!==f.C||e.B!==f.B||e.A!==f.A||e.L!==f.L||e.K!==f.K||e.h!==f.h||e.m!==f.m||e.N!==f.N||e.M!==f.M||e.j!==f.j|| +e.l!==f.l||e.R!==f.R||e.H!==f.H||e.s!==f.s||e.P!==f.P||e.T!==f.T||e.J!==f.J||e.I!==f.I||e.c!==f.c||e.v!==f.v||e.g!==f.g||e.f!==f.f||e.u!==f.u?!1:!0}if(e=e&&c.s===d.s&&c.I===d.I&&c.v===d.v&&c.P===d.P)e=c.h,f=d.h,e=e===f?!0:null===e||null===f?!1:e.b!==f.b||e.a!==f.a?!1:!0;if(e=e&&c.L===d.L&&c.K===d.K&&c.D===d.D&&L(c.g,d.g)&&c.F===d.F)e=c.f,f=d.f,e=e===f?!0:null===e||null===f?!1:L(e.a,f.a)&&e.f===f.f&&L(e.b,f.b)&&e.c===f.c?!0:!1;e&&(e=c.i,f=d.i,e=e===f?!0:null===e||null===f?!1:e.a!==f.a||e.c!==f.c|| +e.b!==f.b?!1:!0);e&&(e=c.l,f=d.l,e=e===f?!0:null===e||null===f?!1:e.h!==f.h||e.g!==f.g||e.b!==f.b||e.c!==f.c||e.i!==f.i||e.a!==f.a||e.j!==f.j||e.f!==f.f?!1:!0);c=e&&c.A===d.A&&c.B===d.B&&c.w===d.w&&c.R===d.R&&c.J===d.J&&c.G===d.G&&c.C===d.C&&M(c.a,d.a,Tj)&&c.M===d.M&&c.O===d.O&&c.H===d.H&&c.u===d.u&&c.N===d.N?!0:!1}}if(c=c&&a.w===b.w)c=a.j,d=b.j,c=c===d?!0:null===c||null===d?!1:c.c===d.c&&c.h===d.h&&c.f===d.f&&L(c.b,d.b)&&L(c.a,d.a)&&c.g===d.g?!0:!1;if(c=c&&M(a.a,b.a,xj)&&a.v===b.v&&a.F===b.F)if(c= +a.f,d=b.f,c===d)c=!0;else if(null===c||null===d)c=!1;else{if(e=c.C===d.C&&c.F===d.F&&c.u===d.u&&Bf(c.c,d.c)&&c.o===d.o&&c.w===d.w&&c.A===d.A&&M(c.a,d.a,Nf)&&c.v===d.v&&c.j===d.j)if(e=c.g,f=d.g,e===f)e=!0;else if(null===e||null===f)e=!1;else{var g;if(g=e.Da===f.Da&&e.H===f.H){g=e.u;var h=f.u;g=g===h?!0:null===g||null===h?!1:g.b!==h.b||g.c!==h.c||g.a!==h.a?!1:!0}if(g=g&&e.ja===f.ja&&ef(e.i,f.i)&&M(e.a,f.a,ef)&&e.Ca===f.Ca&&e.ta===f.ta&&e.ra===f.ra&&e.R===f.R&&e.ba===f.ba&&e.P===f.P&&e.J===f.J&&e.aa=== +f.aa&&e.T===f.T&&e.Z===f.Z&&e.K===f.K&&e.ka===f.ka&&e.ea===f.ea&&e.W===f.W&&e.da===f.da&&e.ca===f.ca&&e.qa===f.qa&&e.O===f.O&&e.I===f.I&&e.N===f.N)g=e.s,h=f.s,g=g===h?!0:null===g||null===h?!1:g.f!==h.f||g.h!==h.h||g.a!==h.a||g.b!==h.b||g.g!==h.g||g.c!==h.c?!1:!0;g&&(g=e.j,h=f.j,g=g===h?!0:null===g||null===h?!1:g.c!==h.c||g.a!==h.a||g.b!==h.b?!1:!0);if(g=g&&e.la===f.la&&e.ua===f.ua&&L(e.m,f.m)&&e.na===f.na&&e.pa===f.pa&&e.w===f.w&&e.oa===f.oa&&e.Aa===f.Aa&&e.ha===f.ha&&e.Ea===f.Ea&&e.L===f.L&&M(e.c, +f.c,ef)&&e.ma===f.ma&&e.sa===f.sa&&e.ia===f.ia&&e.G===f.G&&e.F===f.F&&e.D===f.D&&e.C===f.C&&e.$===f.$&&e.Ba===f.Ba&&e.va===f.va&&e.wa===f.wa&&e.Y===f.Y&&e.A===f.A&&e.M===f.M&&rf(e.o,f.o)&&e.X===f.X&&M(e.f,f.f,tf)&&e.Fa===f.Fa)g=e.l,h=f.l,g=g===h?!0:null===g||null===h?!1:g.b!==h.b||g.a!==h.a?!1:!0;if(g=g&&M(e.b,f.b,sf)&&e.B===f.B&&e.fa===f.fa&&e.ga===f.ga)g=e.v,h=f.v,g=g===h?!0:null===g||null===h?!1:g.a!==h.a||g.b!==h.b?!1:!0;if(g=g&&e.za===f.za&&e.ya===f.ya)g=e.h,h=f.h,g=g===h?!0:null===g||null=== +h?!1:g.c!==h.c||g.f!==h.f||g.g!==h.g||g.b!==h.b||g.a!==h.a?!1:!0;e=g&&M(e.g,f.g,hf)?!0:!1}if(e=e&&c.H===d.H&&c.l===d.l)e=c.h,f=d.h,e=e===f?!0:null===e||null===f?!1:e.b!==f.b||e.c!==f.c||e.a!==f.a?!1:!0;if(e=e&&c.G===d.G&&M(c.b,d.b,jk)&&c.D===d.D&&L(c.f,d.f))e=c.i,f=d.i,e=e===f?!0:null===e||null===f?!1:e.a!==f.a?!1:!0;c=e&&c.m===d.m&&c.s===d.s&&c.B===d.B?!0:!1}if(c=c&&a.I===b.I&&a.A===b.A)c=a.m,d=b.m,c=c===d?!0:null===c||null===d?!1:c.a!==d.a?!1:!0;c&&(c=a.c,d=b.c,c=c===d?!0:null===c||null===d?!1: +M(c.a,d.a,lg)&&c.b===d.b?!0:!1);if(c=c&&a.B===b.B&&a.G===b.G&&a.C===b.C&&a.u===b.u)c=a.o,d=b.o,c=c===d?!0:null===c||null===d?!1:c.a!==d.a?!1:!0;if(c=c&&a.H===b.H)c=a.h,d=b.h,c=c===d?!0:null===c||null===d?!1:c.j!==d.j||c.a!==d.a||c.c!==d.c||c.l!==d.l||c.m!==d.m||c.o!==d.o||c.s!==d.s||c.g!==d.g||c.b!==d.b||c.f!==d.f||c.i!==d.i||c.h!==d.h?!1:!0;c&&a.D===b.D&&a.K===b.K?(null!=a.s&&null==a.i&&(a.i=cd(a.M,a.s,a.L)),a=L(a.i,b.i)?!0:!1):a=!1}return a}xk.prototype.getExtension=function(){return null}; +function Bk(a,b){for(;u(b);)switch(b.a){case 1:a.a=C(b);break;default:x(b)}};function Dk(){this.a=null}function Ek(){this.c=this.a=this.b=null}function Fk(){this.b=this.a=null}function Gk(){this.b=this.a=null}function Hk(){this.c=this.i=this.j=this.h=this.g=this.f=this.b=this.a=null}function Ik(){this.f=this.g=this.c=this.a=this.b=null}function Jk(){this.b=this.a=null}Dk.prototype.getExtension=function(){return null};Ek.prototype.getExtension=function(){return null};Fk.prototype.getExtension=function(){return null};Gk.prototype.getExtension=function(){return null}; +function Kk(a){if(null===a)a=null;else{var b=new Gk;b.a=null;b.b=null;b.a=a.a;b.b=a.b;a=b}return a}function Lk(a,b){for(;u(b);)switch(b.a){case 1:var c=y(b);a.a=c;break;case 2:c=y(b);a.b=c;break;default:x(b)}}function Mk(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a||a.b!==b.b?!1:!0}Hk.prototype.getExtension=function(){return null};function Nk(){return new Hk} +function Ok(a){if(null===a)a=null;else{var b=new Hk;if(b.a)for(var c=0;c<b.a.length;c++){var d=b.a[c];d&&(d.a=null,d.b=null)}b.a=null;(c=b.b)&&zk(c);b.b=null;b.f=null;b.g=null;b.h=null;b.j=null;b.i=null;b.c=null;b.a=J(a.a,Kk);b.b=a.b?yk(a.b):null;b.f=a.f;b.g=a.g;b.h=a.h;b.j=a.j;b.i=a.i;b.c=a.c;a=b}return a}function Pk(){} +function Qk(a,b){for(;u(b);)switch(b.a){case 1:var c=new Gk;G(b,c,Lk);a.a=a.a||[];a.a.push(c);break;case 2:c=new wk;G(b,c,Ak);a.b=c;break;case 3:c=y(b);a.f=c;break;case 5:c=y(b);a.g=c;break;case 6:c=y(b);a.h=c;break;case 7:c=y(b);a.j=c;break;case 9:c=C(b);a.i=c;break;case 10:c=C(b);a.c=c;break;default:x(b)}}function Rk(a,b){return a===b?!0:null===a||null===b?!1:M(a.a,b.a,Mk)&&Ck(a.b,b.b)&&a.f===b.f&&a.g===b.g&&a.h===b.h&&a.j===b.j&&a.i===b.i&&a.c===b.c?!0:!1}Ik.prototype.getExtension=function(){return null}; +Jk.prototype.getExtension=function(){return null};function Sk(){this.a=this.b=this.c=null}function Tk(){this.a=null}function Uk(){this.a=null}Sk.prototype.getExtension=function(){return null};function Vk(){return new Sk}function Wk(a){if(null===a)var b=null;else{b=new Sk;var c=b.c;c&&og(c);b.c=null;if(c=b.b)c.a=null;b.b=null;if(c=b.a)c.a=null;b.a=null;b.c=a.c?ng(a.c):null;if(a.b){c=a.b;var d=new Tk;d.a=null;d.a=c.a;c=d}else c=null;b.b=c;a.a?(a=a.a,c=new Uk,c.a=null,c.a=a.a,a=c):a=null;b.a=a}return b}function Xk(){} +function Yk(a,b){for(;u(b);)switch(b.a){case 1:var c=new mg;G(b,c,pg);a.c=c;break;case 2:c=new Tk;G(b,c,Zk);a.b=c;break;case 4:c=new Uk;G(b,c,$k);a.a=c;break;default:x(b)}}function al(a,b){if(a===b)b=!0;else if(null===a||null===b)b=!1;else{var c;if(c=qg(a.c,b.c)){c=a.b;var d=b.b;c=c===d?!0:null===c||null===d?!1:c.a!==d.a?!1:!0}c&&(a=a.a,b=b.a,c=a===b?!0:null===a||null===b?!1:a.a!==b.a?!1:!0);b=c?!0:!1}return b}Tk.prototype.getExtension=function(){return null}; +function Zk(a,b){for(;u(b);)switch(b.a){case 1:a.a=C(b);break;default:x(b)}}Uk.prototype.getExtension=function(){return null};function $k(a,b){for(;u(b);)switch(b.a){case 1:a.a=A(b);break;default:x(b)}};function bl(){this.a=this.h=this.b=this.c=this.g=this.f=null}bl.prototype.getExtension=function(){return null};function cl(){this.a=null}cl.prototype.getExtension=function(){return null};function dl(a,b){for(;u(b);)switch(b.a){case 1:a.a=C(b);break;default:x(b)}};function el(){this.j=this.o=this.g=this.m=this.f=this.b=this.i=this.s=this.h=this.c=this.a=this.l=null}function fl(a){a.l=null;a.a=null;a.c=null;var b=a.h;b&&Gi(b);a.h=null;a.s=null;a.i=null;a.b=null;a.f=null;a.m=null;if(b=a.g)b.a=null;a.g=null;a.o=null;a.j=null}el.prototype.getExtension=function(){return null}; +function gl(a,b){for(;u(b);)switch(b.a){case 1:var c=A(b);a.l=c;break;case 2:c=C(b);a.a=a.a||[];a.a.push(c);break;case 3:c=C(b);a.c=a.c||[];a.c.push(c);break;case 4:c=new Ei;G(b,c,Hi);a.h=c;break;case 5:c=C(b);a.s=c;break;case 6:c=C(b);a.i=c;break;case 7:c=y(b);a.b=a.b||[];a.b.push(c);break;case 8:c=C(b);a.f=a.f||[];a.f.push(c);break;case 9:c=z(b);a.m=c;break;case 10:c=new cl;G(b,c,dl);a.g=c;break;case 11:c=C(b);a.o=c;break;case 12:c=y(b);a.j=c;break;default:x(b)}};function hl(){this.a=null}hl.prototype.getExtension=function(){return null};function il(){return new hl}function jl(a){if(null===a)var b=null;else{b=new hl;var c=b.a;c&&fl(c);b.a=null;if(a.a){c=new el;a=a.a;fl(c);c.l=a.l;c.a=I(a.a);c.c=I(a.c);c.h=a.h?Fi(a.h):null;c.s=a.s;c.i=a.i;c.b=I(a.b);c.f=I(a.f);c.m=a.m;if(a.g){var d=new cl;var e=a.g;d.a=null;d.a=e.a}else d=null;c.g=d;c.o=a.o;c.j=a.j}else c=null;b.a=c}return b}function kl(){} +function ll(a,b){for(;u(b);)switch(b.a){case 1:var c=new el;G(b,c,gl);a.a=c;break;default:x(b)}}function ml(a,b){if(a===b)a=!0;else if(null===a||null===b)a=!1;else{a=a.a;b=b.a;var c;if(!(c=a===b)){if(null===a||null===b)a=0;else{if(c=a.l===b.l&&L(a.a,b.a)&&L(a.c,b.c)&&Ii(a.h,b.h)&&a.s===b.s&&a.i===b.i&&L(a.b,b.b)&&L(a.f,b.f)&&a.m===b.m){c=a.g;var d=b.g;c=c===d?!0:null===c||null===d?!1:c.a!==d.a?!1:!0}a=c&&a.o===b.o&&a.j===b.j}c=a}a=c?!0:!1}return a};function nl(){this.a=null}nl.prototype.getExtension=function(){return null};function ol(){this.a=null}ol.prototype.getExtension=function(){return null};function pl(){this.j=this.b=this.c=this.a=this.i=this.h=this.f=this.g=null}function ql(){this.a=null}pl.prototype.getExtension=function(){return null};function rl(){return new pl}function sl(a){if(null===a)a=null;else{var b=new pl;b.g=null;b.f=null;b.h=null;b.i=null;b.a=null;b.c=null;b.b=null;b.j=null;b.g=a.g;b.f=a.f;b.h=a.h;b.i=a.i;b.a=a.a;b.c=a.c;b.b=a.b;b.j=a.j;a=b}return a}function tl(){} +function ul(a,b){for(;u(b);)switch(b.a){case 1:var c=A(b);a.g=c;break;case 2:c=A(b);a.f=c;break;case 3:c=D(b);a.h=c;break;case 4:c=D(b);a.i=c;break;case 5:c=A(b);a.a=c;break;case 6:c=z(b);a.c=c;break;case 7:c=z(b);a.b=c;break;case 8:c=z(b);a.j=c;break;default:x(b)}}function vl(a,b){return a===b?!0:null===a||null===b?!1:a.g!==b.g||a.f!==b.f||a.h!==b.h||a.i!==b.i||a.a!==b.a||a.c!==b.c||a.b!==b.b||a.j!==b.j?!1:!0}ql.prototype.getExtension=function(){return null};H(U,53863091,11,rl,tl,ul,sl,vl); +H(U,32819068,11,xg,Dg,Eg,yg,Hg);H(U,42466818,11,Kg,Ng,Og,Lg,Qg);H(U,52617685,11,function(){return new vg},function(){},Tg,function(a){return null===a?null:Cg(a)},Jg);H(U,40154408,11,il,kl,ll,jl,ml);H(U,30096869,11,Vk,Xk,Yk,Wk,al);H(U,51650189,11,hd,ld,md,id,od); +H(U,177034656,11,function(){return new ql},function(){},function(a,b){for(;u(b);)switch(b.a){case 1:a.a=z(b);break;default:x(b)}},function(a){if(null===a)a=null;else{var b=new ql;b.a=null;b.a=a.a;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a?!1:!0});H(Nh,28517612,11,Nk,Pk,Qk,Ok,Rk); +H(Nh,48343962,11,function(){return new Ik},function(){},function(a,b){for(;u(b);)switch(b.a){case 1:var c=z(b);a.b=c;break;case 2:c=new wk;G(b,c,Ak);a.a=c;break;case 3:c=A(b);a.c=c;break;case 4:c=A(b);a.g=c;break;case 5:c=A(b);a.f=c;break;default:x(b)}},function(a){if(null===a)a=null;else{var b=new Ik;b.b=null;var c=b.a;c&&zk(c);b.a=null;b.c=null;b.g=null;b.f=null;b.b=a.b;b.a=a.a?yk(a.a):null;b.c=a.c;b.g=a.g;b.f=a.f;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.b===b.b&&Ck(a.a, +b.a)&&a.c===b.c&&a.g===b.g&&a.f===b.f?!0:!1});H(Nh,49095464,11,function(){return new Jk},function(){},function(a,b){for(;u(b);)switch(b.a){case 1:var c=y(b);a.a=c;break;case 2:c=y(b);a.b=c;break;default:x(b)}},function(a){if(null===a)a=null;else{var b=new Jk;b.a=null;b.b=null;b.a=a.a;b.b=a.b;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a||a.b!==b.b?!1:!0});H(Nh,30096869,11,Vk,Xk,Yk,Wk,al); +H(Nh,132080860,11,function(){return new nl},function(){},function(a,b){for(;u(b);)switch(b.a){case 1:a.a=A(b);break;default:x(b)}},function(a){if(null===a)a=null;else{var b=new nl;b.a=null;b.a=a.a;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a?!1:!0});H(Nh,51650189,11,hd,ld,md,id,od);H(Nh,53863091,11,rl,tl,ul,sl,vl); +H(R,30929027,11,function(){return new Dk},function(){},function(a,b){for(;u(b);)switch(b.a){case 1:a.a=y(b);break;default:x(b)}},function(a){if(null===a)a=null;else{var b=new Dk;b.a=null;b.a=a.a;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a?!1:!0}); +H(R,66786615,11,function(){return new Ek},function(){},function(a,b){for(;u(b);)switch(b.a){case 1:var c=y(b);a.b=c;break;case 2:c=new Zf;G(b,c,dg);a.a=c;break;case 3:c=y(b);a.c=c;break;default:x(b)}},function(a){if(null===a)a=null;else{var b=new Ek;b.b=null;var c=b.a;c&&cg(c);b.a=null;b.c=null;b.b=a.b;b.a=a.a?bg(a.a):null;b.c=a.c;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.b===b.b&&eg(a.a,b.a)&&a.c===b.c?!0:!1});H(R,28517612,11,Nk,Pk,Qk,Ok,Rk); +H(R,30511227,11,function(){return new Ji},function(){},function(a,b){for(;u(b);)switch(b.a){case 1:var c=new Ei;G(b,c,Hi);a.a=c;break;case 3:c=new Ki;G(b,c,Li);a.b=c;break;default:x(b)}},function(a){if(null===a)a=null;else{var b=new Ji,c=b.a;c&&Gi(c);b.a=null;b.b=null;b.a=a.a?Fi(a.a):null;b.b=a.b?new Ki:null;a=b}return a},function(a,b){if(a===b)b=!0;else if(null===a||null===b)b=!1;else{var c;if(c=Ii(a.a,b.a))a=a.b,b=b.b,c=a===b?!0:null===a||null===b?!1:!0;b=c?!0:!1}return b}); +H(R,30096869,11,Vk,Xk,Yk,Wk,al); +H(R,172661375,11,function(){return new bl},function(){},function(a,b){for(;u(b);)switch(b.a){case 1:var c=A(b);a.f=c;break;case 2:c=A(b);a.g=c;break;case 3:c=A(b);a.c=c;break;case 4:c=B(b);a.b=c;break;case 5:c=B(b);a.h=c;break;case 6:c=z(b);a.a=c;break;default:x(b)}},function(a){if(null===a)a=null;else{var b=new bl;b.f=null;b.g=null;b.c=null;b.b=null;b.h=null;b.a=null;b.f=a.f;b.g=a.g;b.c=a.c;b.b=a.b;b.h=a.h;b.a=a.a;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.f!==b.f||a.g!== +b.g||a.c!==b.c||a.b!==b.b||a.h!==b.h||a.a!==b.a?!1:!0});H(R,33356690,11,function(){return new ol},function(){},function(a,b){for(;u(b);)switch(b.a){case 1:a.a=C(b);break;default:x(b)}},function(a){if(null===a)a=null;else{var b=new ol;b.a=null;b.a=a.a;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a?!1:!0}); +H(R,40251317,11,function(){return new Fk},function(){},function(a,b){for(;u(b);)switch(b.a){case 1:var c=y(b);a.a=c;break;case 2:c=y(b);a.b=c;break;default:x(b)}},function(a){if(null===a)a=null;else{var b=new Fk;b.a=null;b.b=null;b.a=a.a;b.b=a.b;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a||a.b!==b.b?!1:!0}); +H(R,43229016,11,function(){return new Di},function(){},function(a,b){for(;u(b);)switch(b.a){case 1:var c=D(b);a.g=c;break;case 2:c=A(b);a.b=c;break;case 3:c=A(b);a.c=c;break;case 4:c=y(b);a.h=c;break;case 5:c=A(b);a.f=c;break;case 6:c=A(b);a.a=a.a||[];a.a.push(c);break;default:x(b)}},function(a){if(null===a)a=null;else{var b=new Di;b.g=null;b.b=null;b.c=null;b.h=null;b.f=null;b.a=null;b.g=a.g;b.b=a.b;b.c=a.c;b.h=a.h;b.f=a.f;b.a=I(a.a);a=b}return a},function(a,b){return a===b?!0:null===a||null===b? +!1:a.g===b.g&&a.b===b.b&&a.c===b.c&&a.h===b.h&&a.f===b.f&&L(a.a,b.a)?!0:!1});H(R,51650189,11,hd,ld,md,id,od);H(R,40154408,11,il,kl,ll,jl,ml); +H(R,60681369,11,function(){return new Ci},function(){},function(a,b){for(;u(b);)switch(b.a){case 1:var c=A(b);a.a=c;break;case 2:c=A(b);a.b=c;break;case 3:c=A(b);a.c=c;break;default:x(b)}},function(a){if(null===a)a=null;else{var b=new Ci;b.a=null;b.b=null;b.c=null;b.a=a.a;b.b=a.b;b.c=a.c;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.a!==b.a||a.b!==b.b||a.c!==b.c?!1:!0}); +H(R,135491995,11,function(){return new Bi},function(){},function(a,b){for(;u(b);)switch(b.a){case 1:var c=A(b);a.c=c;break;case 2:c=E(b);a.g=c;break;case 3:c=A(b);a.b=c;break;case 4:c=z(b);a.f=c;break;case 5:c=A(b);a.a=c;break;default:x(b)}},function(a){if(null===a)a=null;else{var b=new Bi;b.c=null;b.g=null;b.b=null;b.f=null;b.a=null;b.c=a.c;b.g=a.g;b.b=a.b;b.f=a.f;b.a=a.a;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.c!==b.c||a.g!==b.g||a.b!==b.b||a.f!==b.f||a.a!==b.a?!1:!0}); +H(R,137907910,11,function(){return new yi},function(){},function(a,b){for(;u(b);)switch(b.a){case 2:var c=new zi;G(b,c,Ai);a.a=c;break;case 3:c=C(b);a.b=c;break;default:x(b)}},function(a){if(null===a)a=null;else{var b=new yi,c=b.a;c&&(c.a=null,c.b=null);b.a=null;b.b=null;if(a.a){c=a.a;var d=new zi;d.a=null;d.b=null;d.a=c.a;d.b=c.b;c=d}else c=null;b.a=c;b.b=a.b;a=b}return a},function(a,b){if(a===b)a=!0;else if(null===a||null===b)a=!1;else{var c=a.a,d=b.a;a=c!==d&&(null===c||null===d||c.a!==d.a||c.b!== +d.b)||a.b!==b.b?!1:!0}return a});H(R,53863091,11,rl,tl,ul,sl,vl);H(R,42466818,11,Kg,Ng,Og,Lg,Qg);H(Zh,53863091,11,rl,tl,ul,sl,vl);H(Zh,85448653,11,xg,Dg,Eg,yg,Hg);H(U,69077470,8);H(Zh,36512758,8);function wl(a){return 255<a&&xl[a]?xl[a]:a}var xl,V=[];V[8364]=128;V[8218]=130;V[402]=131;V[8222]=132;V[8230]=133;V[8224]=134;V[8225]=135;V[710]=136;V[8240]=137;V[352]=138;V[8249]=139;V[338]=140;V[381]=142;V[8216]=145;V[8217]=146;V[8220]=147;V[8221]=148;V[8226]=149;V[8211]=150;V[8212]=151;V[732]=152;V[8482]=153;V[353]=154;V[8250]=155;V[339]=156;V[382]=158;V[376]=159;xl=V;function yl(){this.b=2;this.a=0;this.c=-1;this.g=0;this.f=da}var zl=function(){if(!Ea||Oa(12))return!1;if(Oa(11)){var a=new Uint8Array(1);a[0]=128;a=l.URL.createObjectURL(new Blob([a]));var b=new XMLHttpRequest;b.open("GET",a,!1);b.overrideMimeType("application/octet-stream; charset=x-user-defined");b.send();l.URL.revokeObjectURL(a);if(128==(b.responseText.charCodeAt(0)&255))return!1}return!0}(); +function Al(a,b){for(a.g=b.length;;)switch(a.b){case 2:var c=a;b.length<c.a+4?c=!1:"X"!=b[c.a]||"H"!=b[c.a+1]||"R"!=b[c.a+2]||"1"!=b[c.a+3]?(c.b=1,c=!1):(c.a+=4,c.b=3,c=!0);if(!c)return!1;break;case 3:c=a;b.length<c.a+4?c=!1:(c.c=Bl(b,c.a)<<24|Bl(b,c.a+1)<<16|Bl(b,c.a+2)<<8|Bl(b,c.a+3),c.a+=4,0>c.c?(c.b=1,c=!1):(c.b=4,c=!0));if(!c)return!1;break;case 4:return b.length<a.a+a.c?b=!1:(a.f(b.substr(a.a,a.c)),a.a+=a.c,a.c=-1,a.b=3,b=b.length>a.a),b?!0:!1;default:return!1}} +function Bl(a,b){return zl?wl(a.charCodeAt(b)):a.charCodeAt(b)&255};function Cl(){};function Dl(a,b){this.o=a;this.l=b;this.m=1;this.a=El(this);this.f="";this.i=500;this.c=!1;this.b=null;this.g=0;this.h=!1}function Fl(a,b,c){m(c)&&(a.m=c);a.h=!0;Pb(a.a,b,void 0,void 0);a.h=!1}function Gl(a){return a.a?Xb(a.a):a.i}Dl.prototype.cancel=function(){var a=this.a;Hl(this,!1);a&&a.abort()}; +function El(a){var b=new Mb;b.m=Math.max(0,0);kb(b,"readystatechange",function(){Il(this,!1)},void 0,a);kb(b,"success",function(){Il(this,!0)},void 0,a);kb(b,"error",a.j,void 0,a);kb(b,"abort",a.j,void 0,a);return b}function Il(a,b){b&&Hl(a,!0);if(!(a.c||null!==a.b||a.h&&0==(a.a?Zb(a.a):a.f).length)){var c=ja();!b&&10>c-a.g?a.b=l.setTimeout(function(){Jl(a)},a.g+10-c):Jl(a)}}function Jl(a){a.b=null;for(var b=a.start();b!==Cl;)b=b.apply(a)} +Dl.prototype.start=function(){this.g=ja();if(this.o())return this.start;this.c=!1;return Cl};Dl.prototype.j=function(){this.l();Hl(this,!1)};function Hl(a,b){!b&&a.c&&(a.c=!1,(void 0).mb(a));null!=a.b&&(l.clearTimeout(a.b),a.b=null);if(a.a){a.f=Zb(a.a);a.i=Xb(a.a);if(b=a.a)if($a(b))b.U&&gb(b.U);else if(b=pb(b)){var c=0,d;for(d in b.a)for(var e=b.a[d].concat(),f=0;f<e.length;++f)ub(e[f])&&++c}a.a=null}};function Kl(a){this.i=!!a;this.f=this.a=this.b=null;this.c=new yl}function Ll(a,b,c,d,e){a.b=new Dl(n(a.g,a),n(a.h,a));a.a=e||null;a.c.f=c;a.f=d||da;if(e){var f=a.b;ac(e,function(){f.cancel();return!0})}a.b.a.o=a.i;Fl(a.b,b,e?1:void 0)}Kl.prototype.g=function(){if(null!=this.a&&3==this.a.a)return!1;var a=this.b;a=Al(this.c,a.a?Zb(a.a):a.f);!a&&null===this.b.a&&Ml(this);return a};Kl.prototype.h=function(){null!=this.a&&3==this.a.a||Ml(this)}; +function Ml(a){var b=a.c;if(3!=b.b||b.g>b.a||!Bb(Gl(a.b)))switch(Gl(a.b)){case 400:a.a&&bc(a.a,4);break;case 404:a.a&&bc(a.a,5);break;default:a.a&&bc(a.a,2)}a.f()};function Nl(a,b){a=new Uint8Array(a,0,a.byteLength);if(4>a.length||88!=a[0]||72!=a[1]||82!=a[2]||49!=a[3])return!1;for(var c=4;c+4<a.length;){var d=a[c]<<24|a[c+1]<<16|a[c+2]<<8|a[c+3];c+=4;if(c+d>a.length)break;b(a.subarray(c,c+d));c+=d}return c!=a.length?!1:!0};function Ol(a,b){b=m(b)?b:0;a.buffer?Pl(a.buffer,a.byteOffset+b,a.length-b):Pl(a,b,a.byteLength-b)}function Pl(a,b,c){c=b+c;var d=b+3&-4,e=c&-4;if(e>d){var f=e-d>>2,g=new Uint8Array(a);for(a=new Int32Array(a,d,f);b<d;b++)g[b]^=155;for(b=0;b<f;b++)a[b]^=2610666395;b=e}else g=new Uint8Array(a);for(;b<c;b++)g[b]^=155};function Ql(){this.h=new Uint32Array(3072);this.g=0;this.f=new Int32Array(1024);this.a=0;this.c=[];this.b=0;this.i=!1}Ql.prototype.reset=function(){this.a=this.g=0;this.i=!1;this.b=0};function Rl(a){a.a=0;a.b=0}function Sl(a){a.a=0;a.b=0}function Tl(a,b,c){var d=a.a/2,e=0==c?2:1;c=0==c?1:2;for(var f=0;f<d-2;f++)Ul(a,b),Ul(a,(b+f+e)%d),Ul(a,(b+f+c)%d)}function Vl(a,b,c){var d=a.f;var e=a.a+1;e>=d.length&&(e=new Int32Array(2*e),e.set(d),d=e);a.f=d;a.f[a.a]=b;a.f[a.a+1]=c;a.a+=2} +function Ul(a,b){a.i?(a.c[2*a.b]=a.f[2*b],a.c[2*a.b+1]=a.f[2*b+1],a.b=(a.b+1)%3,0==a.b&&Wl(a)):Xl(a,a.f[2*b],a.f[2*b+1])}function Wl(a){function b(a,b,c,d){a=c-a;b=d-b;return a*a+b*b}var c=a.c[0],d=a.c[1],e=a.c[2],f=a.c[3],g=a.c[4],h=a.c[5],r=!1;if(262144<b(c,d,e,f)||262144<b(e,f,g,h)||262144<b(g,h,c,d))r=!0;if(r){r=(c+e+g)/3;var v=(d+f+h)/3;Yl(a,r,v,c,d,e,f);Yl(a,r,v,e,f,g,h);Yl(a,r,v,g,h,c,d)}else Xl(a,c,d),Xl(a,e,f),Xl(a,g,h)} +function Yl(a,b,c,d,e,f,g){f-=d;g-=e;var h=Math.ceil(Math.sqrt(f*f+g*g)/512);f/=h;g/=h;for(var r=0;r<h;r++)Xl(a,b,c),Xl(a,d+f*r,e+g*r),Xl(a,d+f*(r+1),e+g*(r+1))}function Xl(a,b,c){var d=a.h;var e=a.g;e>=d.length&&(e=new Uint32Array(2*e),e.set(d),d=e);a.h=d;d=a.g;a.h[d++]=(b&65535|(c&65535)<<16)>>>0;a.g=d};function W(a){this.length=a.length||a;for(var b=0;b<this.length;b++)this[b]=a[b]||0}W.prototype.a=4;W.prototype.set=function(a,b){b=b||0;for(var c=0;c<a.length&&b+c<this.length;c++)this[b+c]=a[c]};W.prototype.toString=Array.prototype.join;"undefined"==typeof Float32Array&&(W.BYTES_PER_ELEMENT=4,W.prototype.BYTES_PER_ELEMENT=W.prototype.a,W.prototype.set=W.prototype.set,W.prototype.toString=W.prototype.toString,ca("Float32Array",W));function Z(a){this.length=a.length||a;for(var b=0;b<this.length;b++)this[b]=a[b]||0}Z.prototype.a=8;Z.prototype.set=function(a,b){b=b||0;for(var c=0;c<a.length&&b+c<this.length;c++)this[b+c]=a[c]};Z.prototype.toString=Array.prototype.join;if("undefined"==typeof Float64Array){try{Z.BYTES_PER_ELEMENT=8}catch(a){}Z.prototype.BYTES_PER_ELEMENT=Z.prototype.a;Z.prototype.set=Z.prototype.set;Z.prototype.toString=Z.prototype.toString;ca("Float64Array",Z)};function Zl(a,b,c,d,e){if(b[d+1]==b[e+1]){var f=c;c=e;e=f}else b[c+1]==b[e+1]&&(f=d,d=e,e=f);b[c+1]!=b[d+1]&&(b[c+1]>b[d+1]&&(f=c,c=d,d=f),b[d+1]>b[e+1]&&(f=d,d=e,e=f),b[c+1]>b[d+1]&&(f=c,c=d,d=f));f=b[c];var g=b[d],h=b[e];c=b[c+1];d=b[d+1];b=b[e+1];c!=b&&(e=f+(d-c)/(b-c)*(h-f),$l(a,Math.min(e,g),h,Math.max(e,g),d,b),c!=d&&$l(a,Math.min(e,g),f,Math.max(e,g),d,c))} +function $l(a,b,c,d,e,f){var g=(c-b)/(f-e);c=(c-d)/(f-e);var h=Math.min(e,f);f=Math.max(e,f);h=Math.max(0,Math.floor(.999+h));for(f=Math.min(255,Math.floor(f));h<=f;h++){var r=h-e,v=b+g*r;r=d+c*r;v=Math.max(0,Math.floor(.999+v));for(r=Math.min(255,Math.floor(r));v<=r;v++)a[256*h+v]=255}};var am=Math.pow(2,22);function bm(){this.a=this.b=this.c=null}bm.prototype.getExtension=function(){return null};H(vi,96629873,11,function(){return new bm},function(){},function(a,b){for(;u(b);)switch(b.a){case 1:var c=y(b);a.c=c;break;case 2:c=z(b);a.b=c;break;case 3:c=z(b);a.a=c;break;default:x(b)}},function(a){if(null===a)a=null;else{var b=new bm;b.c=null;b.b=null;b.a=null;b.c=a.c;b.b=a.b;b.a=a.a;a=b}return a},function(a,b){return a===b?!0:null===a||null===b?!1:a.c!==b.c||a.b!==b.b||a.a!==b.a?!1:!0});new function(){};function cm(a){return(a=a.exec(sa))?a[1]:""}(function(){if(nc)return cm(/Firefox\/([0-9.]+)/);if(Ea||Fa||Da)return Na;if(rc)return ya()||p("iPad")||p("iPod")?cm(/CriOS\/([0-9.]+)/):cm(/Chrome\/([0-9.]+)/);if(sc&&!(ya()||p("iPad")||p("iPod")))return cm(/Version\/([0-9.]+)/);if(oc||pc){var a=/Version\/(\S+).*Mobile\/(\S+)/.exec(sa);if(a)return a[1]+"."+a[2]}else if(qc)return(a=cm(/Android\s+([0-9.]+)/))?a:cm(/Version\/([0-9.]+)/);return""})();function dm(a){var b=a.getExtension(96629873);if(b&&(null==b.a?0:b.a))return am;(b=null==a.f)||(b=null==wi(a).a);if(b)return 16;a=wi(a);switch(null==a.a?0:a.a){case 0:return 16;case 2:return 4;case 3:return 8;case 1:return 16;case 4:return 32;case 5:return 64;case 6:return 128;default:return 16}} +function em(a,b){function c(a,c,d){var e=1;c&&(e+=c.length);for(var f=0,g=0,h=0,r=0;r<e;r++){var v=-1;c&&r<e-1&&(v=c[r]);if(a.V())break;for(d?Sl(b):b.a=0;!a.V()&&f!=v;)g+=Kc(a),h+=Kc(a),Vl(b,g,h),f++;if(d)Tl(b,0,1);else{v=b;for(var S=v.a/2,K=0;K<S-2;K++){var T=K%2;Ul(v,K);Ul(v,K+1+T);Ul(v,K+2-T)}}}}if(null!=a.g||null!=a.f||null!=a.b||null!=a.c){b.i=!1;if(null!=a.g||null!=a.f){var d=null!=a.f?!0:!1;d?Sl(b):Rl(b);for(var e=0,f=0,g=Qh(a);!g.V();)e+=Kc(g),f+=Kc(g),Vl(b,e,f);Ec(g);if(null!=a.g){for(e= +$c(a.a,a.g,a.B);!e.V();)Ul(b,e.next());Dc(e)}d&&Tl(b,null==a.f?-1:a.f,0)}null!=a.b&&(d=Rh(a),e=null!=a.l||null!=a.i?Sh(a):null,c(d,e,!0),Ec(d));null!=a.c&&(d=Th(a),a=null!=a.m||null!=a.j?Uh(a):null,c(d,a,!1),Ec(d))}};function fm(){this.a=new Ql};function gm(a,b){b=m(b)?b:0;var c=m(void 0)?void 0:a.byteLength-b;this.a=new Uint8Array(a,b,c);new Int8Array(a,b,c)}function hm(a,b){return a.a[b]+(a.a[b+1]<<8)+(a.a[b+2]<<16)+16777216*a.a[b+3]};/* + + Copyright 2012 Mozilla Foundation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +function im(){this.b=this.i=0;this.h=!1;this.buffer=null}function jm(a,b){var c=a.buffer,d=c?c.byteLength:0;if(b<d)return c;for(var e=512;e<b;)e<<=1;b=new Uint8Array(e);if(c)for(e=0;e<d;++e)b[e]=c[e];return a.buffer=b}function km(a){for(var b,c=a.i;!a.h;)lm(a);b=a.b;b||(a.buffer=new Uint8Array(0));a.i=b;return a.buffer.subarray(c,b)}im.prototype.reset=function(){this.i=0};function mm(a){this.g=null;this.c=this.f=this.a=0;a&&nm(this,a);im.call(this)}ka(mm,im); +function nm(a,b){var c=0;c++;c++;a.g=b;a.a=c;a.f=0;a.c=0;a.i=0;a.b=0;a.h=!1}function om(a,b){this.a=a;this.b=b} +var pm=new Uint32Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),qm=new Uint8Array(pm.length),rm=new Uint8Array(320),sm=new Uint32Array(512),tm=new Uint32Array(512),um=new Uint32Array(512),vm=new Uint32Array([3,4,5,6,7,8,9,10,65547,65549,65551,65553,131091,131095,131099,131103,196643,196651,196659,196667,262211,262227,262243,262259,327811,327843,327875,327907,258,258,258]),wm=new Uint32Array([1,2,3,4,65541,65543,131081,131085,196625,196633,262177,262193,327745,327777,393345,393409,459009, +459137,524801,525057,590849,591361,657409,658433,724993,727041,794625,798721,868353,876545]),xm=new om(new Uint32Array([459008,524368,524304,524568,459024,524400,524336,590016,459016,524384,524320,589984,524288,524416,524352,590048,459012,524376,524312,589968,459028,524408,524344,590032,459020,524392,524328,59E4,524296,524424,524360,590064,459010,524372,524308,524572,459026,524404,524340,590024,459018,524388,524324,589992,524292,524420,524356,590056,459014,524380,524316,589976,459030,524412,524348, +590040,459022,524396,524332,590008,524300,524428,524364,590072,459009,524370,524306,524570,459025,524402,524338,590020,459017,524386,524322,589988,524290,524418,524354,590052,459013,524378,524314,589972,459029,524410,524346,590036,459021,524394,524330,590004,524298,524426,524362,590068,459011,524374,524310,524574,459027,524406,524342,590028,459019,524390,524326,589996,524294,524422,524358,590060,459015,524382,524318,589980,459031,524414,524350,590044,459023,524398,524334,590012,524302,524430,524366, +590076,459008,524369,524305,524569,459024,524401,524337,590018,459016,524385,524321,589986,524289,524417,524353,590050,459012,524377,524313,589970,459028,524409,524345,590034,459020,524393,524329,590002,524297,524425,524361,590066,459010,524373,524309,524573,459026,524405,524341,590026,459018,524389,524325,589994,524293,524421,524357,590058,459014,524381,524317,589978,459030,524413,524349,590042,459022,524397,524333,590010,524301,524429,524365,590074,459009,524371,524307,524571,459025,524403,524339, +590022,459017,524387,524323,589990,524291,524419,524355,590054,459013,524379,524315,589974,459029,524411,524347,590038,459021,524395,524331,590006,524299,524427,524363,590070,459011,524375,524311,524575,459027,524407,524343,590030,459019,524391,524327,589998,524295,524423,524359,590062,459015,524383,524319,589982,459031,524415,524351,590046,459023,524399,524335,590014,524303,524431,524367,590078,459008,524368,524304,524568,459024,524400,524336,590017,459016,524384,524320,589985,524288,524416,524352, +590049,459012,524376,524312,589969,459028,524408,524344,590033,459020,524392,524328,590001,524296,524424,524360,590065,459010,524372,524308,524572,459026,524404,524340,590025,459018,524388,524324,589993,524292,524420,524356,590057,459014,524380,524316,589977,459030,524412,524348,590041,459022,524396,524332,590009,524300,524428,524364,590073,459009,524370,524306,524570,459025,524402,524338,590021,459017,524386,524322,589989,524290,524418,524354,590053,459013,524378,524314,589973,459029,524410,524346, +590037,459021,524394,524330,590005,524298,524426,524362,590069,459011,524374,524310,524574,459027,524406,524342,590029,459019,524390,524326,589997,524294,524422,524358,590061,459015,524382,524318,589981,459031,524414,524350,590045,459023,524398,524334,590013,524302,524430,524366,590077,459008,524369,524305,524569,459024,524401,524337,590019,459016,524385,524321,589987,524289,524417,524353,590051,459012,524377,524313,589971,459028,524409,524345,590035,459020,524393,524329,590003,524297,524425,524361, +590067,459010,524373,524309,524573,459026,524405,524341,590027,459018,524389,524325,589995,524293,524421,524357,590059,459014,524381,524317,589979,459030,524413,524349,590043,459022,524397,524333,590011,524301,524429,524365,590075,459009,524371,524307,524571,459025,524403,524339,590023,459017,524387,524323,589991,524291,524419,524355,590055,459013,524379,524315,589975,459029,524411,524347,590039,459021,524395,524331,590007,524299,524427,524363,590071,459011,524375,524311,524575,459027,524407,524343, +590031,459019,524391,524327,589999,524295,524423,524359,590063,459015,524383,524319,589983,459031,524415,524351,590047,459023,524399,524335,590015,524303,524431,524367,590079]),9),ym=new om(new Uint32Array([327680,327696,327688,327704,327684,327700,327692,327708,327682,327698,327690,327706,327686,327702,327694,0,327681,327697,327689,327705,327685,327701,327693,327709,327683,327699,327691,327707,327687,327703,327695,0]),5); +function zm(a,b){for(var c=a.f,d=a.c,e=a.g,f=a.a,g;c<b;)g=e[f++],d|=g<<c,c+=8;a.c=d>>b;a.f=c-b;a.a=f;return d&(1<<b)-1}function Am(a,b){var c=b.a,d=b.b;b=a.f;for(var e=a.c,f=a.g,g=a.a;b<d;){var h=f[g++];e|=h<<b;b+=8}c=c[e&(1<<d)-1];d=c>>16;a.c=e>>d;a.f=b-d;a.a=g;return c&65535} +function Bm(a,b,c,d){for(var e=0,f=b;f<c;++f)a[f]>e&&(e=a[f]);var g=1<<e;d=g<=d.length?d:new Uint32Array(g);for(var h=1,r=0,v=2;h<=e;++h,r<<=1,v<<=1)for(var F=b;F<c;++F)if(a[F]==h){var X=0,N=r;for(f=0;f<h;++f)X=X<<1|N&1,N>>=1;for(f=X;f<g;f+=v)d[f]=h<<16|F-b;++r}return new om(d,e)} +function lm(a){var b=zm(a,3);b&1&&(a.h=!0);b>>=1;if(0==b){b=a.g;var c=a.a,d,e=d=b[c++];d=b[c++];e|=d<<8;c++;c++;a.c=0;a.f=0;d=a.b;var f=jm(a,d+e);e=d+e;a.b=e;for(var g=d;g<e;++g){if("undefined"==typeof(d=b[c++])){a.h=!0;break}f[g]=d}a.a=c}else{c=xm;d=ym;if(1!=b&&2==b){f=zm(a,5)+257;e=zm(a,5)+1;b=zm(a,4)+4;for(c=0;c<qm.length;++c)qm[c]=0;for(c=0;c<b;++c)qm[pm[c]]=zm(a,3);d=Bm(qm,0,qm.length,sm);c=b=0;for(e=f+e;c<e;){g=Am(a,d);if(16==g){var h=2,r=3;g=b}else if(17==g)r=h=3,g=b=0;else if(18==g)h=7,r= +11,g=b=0;else{rm[c++]=b=g;continue}for(h=zm(a,h)+r;0<h--;)rm[c++]=g}c=Bm(rm,0,f,tm);d=Bm(rm,f,e,um)}e=(f=a.buffer)?f.length:0;for(g=a.b;;)if(h=Am(a,c),256>h)g+1>=e&&(f=jm(a,g+1),e=f.length),f[g++]=h;else{if(256==h){a.b=g;break}h-=257;h=vm[h];r=h>>16;0<r&&(r=zm(a,r));b=(h&65535)+r;h=Am(a,d);h=wm[h];r=h>>16;0<r&&(r=zm(a,r));h=(h&65535)+r;g+b>=e&&(f=jm(a,g+b),e=f.length);for(r=0;r<b;++r,++g)f[g]=f[g-h]}}};/* + + MIT LICENSE + Copyright (c) 2011 Devon Govett + + 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 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. +*/ +function Cm(){this.v=new mm;this.data=new Uint8Array(0);this.a=8;this.g=[];this.o=null;this.b={};this.h=null;this.w={};this.j=this.s=0;this.m=null;this.c=this.l=this.f=this.height=this.width=0;this.i=!1;this.u=0} +function Dm(a){for(var b=null;;){var c=Em(a),d=a,e=String.fromCharCode(d.data[d.a++]);e+=String.fromCharCode(d.data[d.a++]);e+=String.fromCharCode(d.data[d.a++]);e+=String.fromCharCode(d.data[d.a++]);switch(e){case "IHDR":c=a;c.width=Em(c);c.height=Em(c);c.l=c.data[c.a++];c.c=c.data[c.a++];c.a++;c.a++;c.a++;break;case "acTL":c=a;c.h={kb:Em(c),lb:Em(c)||Infinity,frames:[]};break;case "PLTE":d=a;d.s=d.a;d.j=c;d.a+=c;break;case "fcTL":b&&a.h.frames.push(b);b=a;b.a+=4;c={width:Em(b),height:Em(b),ob:Em(b), +pb:Em(b)};d=Fm(b);e=Fm(b)||100;c.hb=1E3*d/e;c.ib=b.data[b.a++];c.fb=b.data[b.a++];c.gb=[];b=c;break;case "fdAT":a.a+=4,c-=4;case "IDAT":d=a;if(b){e=b.data;for(var f=0;f<c;f++)e.push(d.data[d.a++])}else d.g.push(d.a),d.g.push(c),d.a+=c;break;case "tRNS":d=a;d.b={};switch(d.c){case 3:e=c;255>e&&(e=255);d.b.Ma=Array(e);for(f=0;f<c;f++)d.b.Ma[f]=d.data[d.a++];for(f=c;f<e;f++)d.b.Ma[f]=255;break;case 0:d.b.jb=Gm(d,c)[0];break;case 2:d.b.nb=Gm(d,c)}break;case "tEXt":d=a;c=Gm(d,c);e=c.indexOf(0);d.w[String.fromCharCode.apply(String, +c.slice(0,e))]=String.fromCharCode.apply(String,c.slice(e+1));break;case "IEND":b&&a.h.frames.push(b);b=void 0;switch(a.c){case 0:case 3:case 4:a.f=1;break;case 2:case 6:a.f=3}a.i=4===(b=a.c)||6===b;a.u=a.l*(a.f+(a.i?1:0));b=a.g;if(2==b.length)d=new Uint8Array(a.data.buffer.slice(a.data.byteOffset+b[0],a.data.byteOffset+b[0]+b[1]));else{d=0;for(c=1;c<b.length;c+=2)d+=b[c];d=new Uint8Array(d);e=0;f=a.data;for(c=0;c<b.length;c+=2)for(var g=b[c],h=b[c+1],r=0;r<h;r++)d[e++]=f[g+r]}a.o=d;a.g=[];return; +default:a.a+=c}a.a+=4;if(a.a>a.data.length)throw Error("Incomplete or corrupt PNG file");}}function Gm(a,b){for(var c=Array(b),d=0;d<b;d++)c[d]=a.data[a.a++];return c}function Em(a){var b=a.data[a.a++]<<24;var c=a.data[a.a++]<<16;var d=a.data[a.a++]<<8;a=a.data[a.a++];return b|c|d|a}function Fm(a){var b=a.data[a.a++]<<8;a=a.data[a.a++];return b|a} +function Hm(a){var b=null,c,d,e,f,g,h,r,v,F,X;null==b&&(b=a.o);if(0===b.length)return new Uint8Array(0);nm(a.v,b);var N=a.v;N=km(N);b=a.u/8;var Y=b*a.width;var O=new Uint8Array(Y*a.height);var Jm=N.length;for(c=e=f=0;e<Jm;){switch(N[e++]){case 0:for(h=0;h<Y;h+=1)O[c++]=N[e++];break;case 1:for(d=r=0;r<Y;d=r+=1){a=N[e++];var S=d<b?0:O[c-b];O[c++]=(a+S)%256}break;case 2:for(d=v=0;v<Y;d=v+=1){a=N[e++];var K=(d-d%b)/b;var T=f&&O[(f-1)*Y+K*b+d%b];O[c++]=(T+a)%256}break;case 3:for(d=F=0;F<Y;d=F+=1)a=N[e++], +K=(d-d%b)/b,S=d<b?0:O[c-b],T=f&&O[(f-1)*Y+K*b+d%b],O[c++]=(a+Math.floor((S+T)/2))%256;break;case 4:for(d=X=0;X<Y;d=X+=1){a=N[e++];K=(d-d%b)/b;S=d<b?0:O[c-b];0===f?T=g=0:(T=O[(f-1)*Y+K*b+d%b],g=K&&O[(f-1)*Y+(K-1)*b+d%b]);var Aa=S+T-g;K=Math.abs(Aa-S);d=Math.abs(Aa-T);Aa=Math.abs(Aa-g);S=K<=d&&K<=Aa?S:d<=Aa?T:g;O[c++]=(a+S)%256}break;default:throw Error("Invalid filter algorithm: "+N[e-1]);}f++}return O} +function Im(a){var b=a.s,c=a.data,d=a.b.Ma||null;a=a.j;for(var e=new Uint8Array(a/3*4),f=0,g=0,h=0;h<a;h+=3)e[f++]=c[b+h],e[f++]=c[b+h+1],e[f++]=c[b+h+2],e[f++]=d?d[g++]:255;return e} +function Km(a,b,c){var d=a.f;var e=null;var f=a.i;a.j&&(e=a.m=a.m||Im(a),d=4,f=!0);a=b.length;if(1===d)if(e)if(f)for(f=d=0;d<a;d+=4,f++){var g=4*c[f];var h=e[g];b[d]=h;b[d+1]=h;b[d+2]=h;b[d+3]=e[g+1]}else for(f=d=0;d<a;d+=4,f++)g=4*c[f],h=e[g],b[d]=h,b[d+1]=h,b[d+2]=h,b[d+3]=255;else if(f)for(f=d=0;d<a;d+=4,f+=2)h=c[f],b[d]=h,b[d+1]=h,b[d+2]=h,b[d+3]=c[f+1];else for(f=d=0;d<a;d+=4,f++)h=c[f],b[d]=h,b[d+1]=h,b[d+2]=h,b[d+3]=255;else if(e)if(f)for(f=d=0;d<a;d+=4,f++)g=4*c[f],b[d]=e[g],b[d+1]=e[g+1], +b[d+2]=e[g+2],b[d+3]=e[g+3];else for(f=d=0;d<a;d+=4,f++)g=4*c[f],b[d]=e[g],b[d+1]=e[g+1],b[d+2]=e[g+2],b[d+3]=255;else if(f)for(d=0;d<a;d+=4)b[d]=c[d],b[d+1]=c[d+1],b[d+2]=c[d+2],b[d+3]=c[d+3];else for(f=d=0;d<a;d+=4,f+=3)b[d]=c[f],b[d+1]=c[f+1],b[d+2]=c[f+2],b[d+3]=255};function Lm(a){this.c=a;this.f=this.b=null;this.a=this.Va;a=n(this.Ya,this);this.c.a=a}var Mm=null,Nm=null,kc=null;k=Lm.prototype;k.Ya=function(){this.b&&this.b.cancel();this.f&&this.f.abort();return!0}; +function Om(a,b){var c=b.g;if(b.a||!kc||!lc(kc,c,n(a.Va,a))){var d=b.h;if(b.f)d=new Kl(d),a.b=new $b,Ll(d,c,n(a.$a,a,b),n(a.ab,a),a.b);else{var e=new Mb;a.f=e;e.o=d;e.g="arraybuffer";kb(e,"readystatechange",function(){if(Yb(e)&&4==Wb(e)){var c=e.Ia();if(b.c)Pm(a,c);else{var d=new ec;d.b=0;d.c=0;if(c&&0<c.byteLength){d.a=c;var h=[c];Qm(c,b,d,h)}d.status=1;a.a(d,!0,h)}}});kb(e,"error",a.bb,!1,a);Pb(e,c)}b.a&&(kc||(kc=new hc),a.a=ic(c,a.b,a.f))}} +k.$a=function(a,b){var c=new ec;c.status=1;c.b=Bl(b,0);c.c=Bl(b,1);var d=m(void 0)?NaN:b.length;d>b.length&&(d=b.length);if(2>=d||2>=b.length)b=null;else{var e=new Uint8Array(d-2);if(zl)for(var f=2;f<d;++f)e[f-2]=wl(b.charCodeAt(f));else for(f=2;f<d;++f)e[f-2]=b.charCodeAt(f)&255;b=e.buffer}if(b&&0<b.byteLength){c.a=b;var g=[b];Qm(b,a,c,g)}this.a(c,!1,g)};k.ab=function(){var a=new ec;a.status=this.b.a;this.a(a,!0)}; +function Pm(a,b){var c=[],d=Nl(b,function(a){c.push(a);2<a.length&&Ol(a,2)}),e=new ec;d?(e.status=1,e.h=c,a.a(e,!0,[b])):(e.status=2,a.a(e,!0))} +function Qm(a,b,c,d){Ol(a);var e=b.b&2;b=b.b&4;if(e||b){var f=new Mh;a=Qc(a);ui(f,a);Rc(a);if(e){if(null!=f.c){null===f.c&&(f.c=new zh);e=f.c;var g;null!=e.Ka&&null==e.Na&&(e.Na=cd(e.Ra,e.Ka,e.Sa));if(g=e.Na)c.i=Rm(g,d)}if(null!=f.b){e=c.f=[];null===f.b&&(f.b=new Jh);a=f.b;for(var h=0;h<(a.a?a.a.length:0);h++)if(g=a.a[h].getImageData())g=Rm(g,d),e[h]=g}}if(b){null===f.g&&(f.g=new mh);b=f.g;if(12>(null==b.Oa?0:b.Oa)){Nm||(Nm=new fm);b=Nm;a=null;e=[];if(h=null!=f.a?!0:!1)h=null!=xi(f).a?!0:!1;if(h)for(h= +xi(f).a,g=0;g<h.length;g++){var r=h[g],v=r.getExtension(177034656);v&&(null==v.a?0:v.a)&&(null==r.c||!r.c)&&null!=r.a&&e.push(Wh(r))}if(e.length)b:{f=dm(f);a=new Uint8Array(65536);for(h=0;h<e.length;h++){r=e[h];v=b.a;g=f;v.reset();em(r,v);r=v.h.subarray(0,v.g);if(0==r.length)r=null;else{v=new Float32Array(2*r.length);for(var F=0;F<r.length;F++){var X=r[F];v[2*F+0]=(X<<16>>16)/g;v[2*F+1]=(X>>16)/g}r=v}if(!r){a=null;break b}v=r.length/6;if(0!=v)for(g=a,v=v?6*v:r.length,F=0;F<v;F+=6)Zl(g,r,F,F+2,F+4)}a= +new cc(a,256,256,4)}a&&d.push(a.data.buffer);d=a}else d=null;c.g=d}}} +function Rm(a,b){var c=2*(a[0]<<23)+(a[1]<<16)+(a[2]<<8)+a[3];switch(c){case 2303741511:var d="image/png";break;case 4292411360:d="image/jpeg";break;case 1195984440:d="image/gif";break;case 1145328416:d="image/x-dds";break;case 1380533830:d="image/unknown";12<a.length&&(c=2*(a[8]<<23)+(a[9]<<16)+(a[10]<<8)+a[11],1464156752==c&&(d="image/webp"));break;default:d="image/unknown"}switch(d){case "image/x-dds":var e=new gm(a.buffer,a.byteOffset+4),f=hm(e,0)+4;b=hm(e,8);c=hm(e,12);d=hm(e,80);hm(e,76)&4&& +(827611204==d||894720068==d)?(a=new Uint8Array(a.buffer,a.byteOffset+f,a.byteLength-f),a=new cc(a,c,b,827611204==d?2:3)):a=null;return a;case "image/png":return Mm||(Mm=new Cm),c=Mm,c.data=a,c.a=8,c.g=[],c.o=null,c.b={},c.h=null,c.w={},c.s=0,c.j=0,c.m=null,c.width=0,c.height=0,c.f=0,c.l=0,c.c=0,c.i=!1,c.u=0,Dm(c),a=new Uint8Array(c.width*c.height*4),Km(c,a,Hm(c)),b&&b.push(a.buffer),new cc(a,a.length/c.height/4,c.height);default:return null}}k.bb=function(){var a=new ec;a.status=2;this.a(a,!0)}; +k.Va=function(a,b,c){var d={};null!=a.status&&(d.status=a.status);null!=a.b&&(d.prIndex=a.b);null!=a.c&&(d.prStatus=a.c);null!=a.a&&(d.prData=a.a);null!=a.h&&(d.prChunks=a.h);a.i&&(d.spritemapImage=fc(a.i));if(a.f)for(var e=d.rasterRenderOpImages=[],f=0;f<a.f.length;f++)e[f]=fc(a.f[f]);a.g&&(d.computedWaterCoverage=fc(a.g));this.c.postMessage(d,b,c)};function Sm(){var a=self;this.b=a;this.a={};a.onmessage=n(this.f,this);this.c=n(this.g,this);Tm(this,"__worker_started__")} +Sm.prototype.f=function(a){var b=a.data,c=ja();if(a=b.abort){if(b=this.a[a])delete this.a[a],b.abort()||Tm(this,"Cannot abort this task.")}else{var d=b.id;a=b.payload;if(m(d))switch(b.command){case 1:a?(b=new la(d,this.b,this.c),b.b=c,this.a[d]=b,c=new Lm(b),b=new dc,m(a.uri)&&(b.g=a.uri),m(a.xdc)&&(b.h=a.xdc),m(a.streaming)&&(b.f=a.streaming),m(a.chunked)&&(b.c=a.chunked),m(a.deferred)&&(b.a=a.deferred),m(a.workerOptions)&&(b.b=a.workerOptions),Om(c,b)):Tm(this,"Payload required for Xhr command."); +break;case 2:b=new la(d,this.b,this.c);b.b=c;this.a[d]=b;a=c=new Lm(b);kc?(c=kc.a,a.c.postMessage({success:c.b,mismatch:c.a},!0)):a.c.postMessage({},!0);break;default:Tm(this,"Unknown message")}}};function Tm(a,b){var c={};c.logs=[b];a.b.postMessage(c)}Sm.prototype.g=function(a){delete this.a[a]};"undefined"!=typeof WorkerGlobalScope&&new Sm;function Um(){var a=Vm;if("undefined"!=typeof window){var b=function(){return this.getAttribute("src")},c=function(b){b=a.call(this,b);this.setAttribute("src",b)},d=this.a=document.createElement;document.createElement=function(a){var e=d.call(this,a);"IMG"==a.toUpperCase()&&Object.defineProperty(e,"src",{enumerable:!0,configurable:!0,get:b,set:c});return e}}}Um.prototype.h=function(){"undefined"!=typeof window&&(document.createElement=this.a)};function Wm(){var a=Vm,b=this.a=XMLHttpRequest.prototype.open;XMLHttpRequest.prototype.open=function(c,d,e,f,g){for(var h=a.call(this,d),r=Array(arguments.length),v=0;v<r.length;v++)r[v]=1==v?h:arguments[v];b.apply(this,r)}}Wm.prototype.h=function(){XMLHttpRequest.prototype.open=this.a};function Xm(){this.h=this.b=this.g=this.a=this.f=this.c=null}function Ym(){this.a=null}Xm.prototype.getExtension=function(){return null};function Zm(a,b){for(a.h=b.b.b;u(b);)switch(b.a){case 1:var c=A(b);a.c=c;break;case 2:null===a.a&&(a.a=b.c);w(b);a.g=b.b.a;break;case 3:c=A(b);a.b=c;break;case 4:y(b);break;default:x(b)}}Xm.prototype.Ia=function(){null!=this.a&&null==this.f&&(this.f=cd(this.h,this.a,this.g));return this.f};Ym.prototype.getExtension=function(){return null};var $m={},an=null,bn=null;function Vm(a){return $m[a]||a};(function(a,b){an&&an.h();an=new Um;bn&&bn.h();bn=new Wm;for(var c in $m)URL.revokeObjectURL($m[c]);$m={};c=new Mb;c.g="arraybuffer";nb(c,"complete",function(){if(Yb(this)){var a=this.Ia(),c=new Ym;for(a=Qc(a);u(a);)switch(a.a){case 1:var f=new Xm;G(a,f,Zm);c.a=c.a||[];c.a.push(f);break;default:x(a)}Rc(a);for(a=0;a<(c.a?c.a.length:0);a++)f=c.a[a],$m[null==f.c?"":f.c]=URL.createObjectURL(new Blob([f.Ia()],{type:null==f.b?"":f.b}));b()}else throw Error("Failed to load dataset.");});Pb(c,a)})("load_dataset", +function(){self.postMessage("dataset_loaded")});}).call(this);
diff --git a/tools/perf/page_sets/system_health/expectations.py b/tools/perf/page_sets/system_health/expectations.py index 7df3e4e1..a3555e1 100644 --- a/tools/perf/page_sets/system_health/expectations.py +++ b/tools/perf/page_sets/system_health/expectations.py
@@ -25,6 +25,8 @@ [expectations.ALL], 'crbug.com/769809') self.DisableStory('browse:tools:maps', [expectations.ALL_MAC], 'crbug.com/773084') + self.DisableStory('load:media:youtube', [expectations.ALL_MAC], + 'crbug.com/795585') class SystemHealthDesktopMemoryExpectations(expectations.StoryExpectations):
diff --git a/tools/perf/page_sets/tough_filters_cases.py b/tools/perf/page_sets/tough_filters_cases.py index 1056d1a..faaa1aa 100644 --- a/tools/perf/page_sets/tough_filters_cases.py +++ b/tools/perf/page_sets/tough_filters_cases.py
@@ -38,11 +38,11 @@ urls_list = [ ('http://rawgit.com/WebKit/webkit/master/PerformanceTests/Animometer/developer.html?test-interval=20&display=minimal&controller=fixed&frame-rate=50&kalman-process-error=1&kalman-measurement-error=4&time-measurement=performance&suite-name=Animometer&test-name=Focus&complexity=100', # pylint: disable=line-too-long - 'MotionMark Focus'), + 'MotionMark_Focus'), ('http://letmespellitoutforyou.com/samples/svg/filter_terrain.svg', - 'Filter Terrain SVG'), + 'Filter_Terrain_SVG'), ('http://static.bobdo.net/Analog_Clock.svg', - 'Analog Clock SVG'), + 'Analog_Clock_SVG'), ] for url, name in urls_list: @@ -51,5 +51,5 @@ pirate_url = ('http://web.archive.org/web/20150502135732/' 'http://ie.microsoft.com/testdrive/Performance/' 'Pirates/Default.html') - name = 'IE PirateMark' + name = 'IE_PirateMark' self.AddStory(PirateMarkPage(pirate_url, self, name=name))
diff --git a/tools/perf/page_sets/tough_path_rendering_cases.py b/tools/perf/page_sets/tough_path_rendering_cases.py index debbabf..d9c090a 100644 --- a/tools/perf/page_sets/tough_path_rendering_cases.py +++ b/tools/perf/page_sets/tough_path_rendering_cases.py
@@ -31,11 +31,11 @@ cloud_storage_bucket=story.PARTNER_BUCKET) page_list = [ - ('GUIMark Vector Chart Test', + ('GUIMark_Vector_Chart_Test', 'http://www.craftymind.com/factory/guimark2/HTML5ChartingTest.html'), - ('MotionMark Canvas Fill Shapes', + ('MotionMark_Canvas_Fill_Shapes', 'http://rawgit.com/WebKit/webkit/master/PerformanceTests/MotionMark/developer.html?test-name=Fillshapes&test-interval=20&display=minimal&tiles=big&controller=fixed&frame-rate=50&kalman-process-error=1&kalman-measurement-error=4&time-measurement=performance&suite-name=Canvassuite&complexity=1000'), # pylint: disable=line-too-long - ('MotionMark Canvas Stroke Shapes', + ('MotionMark_Canvas_Stroke_Shapes', 'http://rawgit.com/WebKit/webkit/master/PerformanceTests/MotionMark/developer.html?test-name=Strokeshapes&test-interval=20&display=minimal&tiles=big&controller=fixed&frame-rate=50&kalman-process-error=1&kalman-measurement-error=4&time-measurement=performance&suite-name=Canvassuite&complexity=1000'), # pylint: disable=line-too-long ] @@ -47,5 +47,5 @@ # http://ie.microsoft.com/testdrive/Performance/Chalkboard/. chalkboard_url = ('https://testdrive-archive.azurewebsites.net' '/performance/chalkboard/') - name = 'IE Chalkboard' + name = 'IE_Chalkboard' self.AddStory(ChalkboardPage(chalkboard_url, self, name=name))
diff --git a/ui/app_list/views/app_list_main_view.cc b/ui/app_list/views/app_list_main_view.cc index 49ad46b..24c0bf2 100644 --- a/ui/app_list/views/app_list_main_view.cc +++ b/ui/app_list/views/app_list_main_view.cc
@@ -50,8 +50,8 @@ search_box_view_(nullptr), contents_view_(nullptr), app_list_view_(app_list_view) { - SetLayoutManager( - new views::BoxLayout(views::BoxLayout::kVertical, gfx::Insets(), 0)); + SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::kVertical, gfx::Insets(), 0)); model_->AddObserver(this); }
diff --git a/ui/app_list/views/page_switcher_horizontal.cc b/ui/app_list/views/page_switcher_horizontal.cc index 0ebbfcbc..fa115bf 100644 --- a/ui/app_list/views/page_switcher_horizontal.cc +++ b/ui/app_list/views/page_switcher_horizontal.cc
@@ -223,7 +223,7 @@ button_width = std::min(kMaxButtonWidth, std::max(kMinButtonWidth, button_width)); - buttons_->SetLayoutManager(new views::BoxLayout( + buttons_->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::kHorizontal, gfx::Insets(0, kButtonStripPadding), button_spacing)); for (int i = 0; i < button_count; ++i) {
diff --git a/ui/app_list/views/page_switcher_vertical.cc b/ui/app_list/views/page_switcher_vertical.cc index 8f5aacb..05a652a 100644 --- a/ui/app_list/views/page_switcher_vertical.cc +++ b/ui/app_list/views/page_switcher_vertical.cc
@@ -172,7 +172,7 @@ SetPaintToLayer(); layer()->SetFillsBoundsOpaquely(false); - buttons_->SetLayoutManager(new views::BoxLayout( + buttons_->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::kVertical, gfx::Insets(), kButtonPadding)); AddChildView(buttons_);
diff --git a/ui/app_list/views/search_box_view.cc b/ui/app_list/views/search_box_view.cc index 826a3a10..3d15260 100644 --- a/ui/app_list/views/search_box_view.cc +++ b/ui/app_list/views/search_box_view.cc
@@ -222,7 +222,7 @@ SetPaintToLayer(); layer()->SetFillsBoundsOpaquely(false); - SetLayoutManager(new views::FillLayout); + SetLayoutManager(std::make_unique<views::FillLayout>()); SetPreferredSize(gfx::Size(kPreferredWidth, kSearchBoxPreferredHeight)); UpdateSearchBoxBorder(); AddChildView(content_container_); @@ -230,11 +230,12 @@ content_container_->SetBackground( std::make_unique<SearchBoxBackground>(background_color_)); - box_layout_ = new views::BoxLayout( - views::BoxLayout::kHorizontal, gfx::Insets(0, kPadding), - kInnerPadding - views::LayoutProvider::Get()->GetDistanceMetric( - views::DISTANCE_TEXTFIELD_HORIZONTAL_TEXT_PADDING)); - content_container_->SetLayoutManager(box_layout_); + box_layout_ = + content_container_->SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::kHorizontal, gfx::Insets(0, kPadding), + kInnerPadding - + views::LayoutProvider::Get()->GetDistanceMetric( + views::DISTANCE_TEXTFIELD_HORIZONTAL_TEXT_PADDING))); box_layout_->set_cross_axis_alignment( views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); box_layout_->set_minimum_cross_axis_size(kSearchBoxPreferredHeight);
diff --git a/ui/app_list/views/search_result_actions_view.cc b/ui/app_list/views/search_result_actions_view.cc index 75be730..ef36bb1 100644 --- a/ui/app_list/views/search_result_actions_view.cc +++ b/ui/app_list/views/search_result_actions_view.cc
@@ -23,8 +23,8 @@ SearchResultActionsViewDelegate* delegate) : delegate_(delegate), selected_action_(-1) { - SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, - gfx::Insets(10, 0), 0)); + SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::kHorizontal, gfx::Insets(10, 0), 0)); } SearchResultActionsView::~SearchResultActionsView() {}
diff --git a/ui/app_list/views/search_result_answer_card_view.cc b/ui/app_list/views/search_result_answer_card_view.cc index cb661ba..9408c26 100644 --- a/ui/app_list/views/search_result_answer_card_view.cc +++ b/ui/app_list/views/search_result_answer_card_view.cc
@@ -35,12 +35,12 @@ : Button(this), view_delegate_(view_delegate) { SetFocusBehavior(FocusBehavior::ALWAYS); // Center the card horizontally in the container. - views::BoxLayout* answer_container_layout = - new views::BoxLayout(views::BoxLayout::kHorizontal, - gfx::Insets(kVerticalPadding, kHorizontalPadding)); + auto answer_container_layout = std::make_unique<views::BoxLayout>( + views::BoxLayout::kHorizontal, + gfx::Insets(kVerticalPadding, kHorizontalPadding)); answer_container_layout->set_main_axis_alignment( views::BoxLayout::MAIN_AXIS_ALIGNMENT_START); - SetLayoutManager(answer_container_layout); + SetLayoutManager(std::move(answer_container_layout)); } ~SearchAnswerContainerView() override { @@ -151,7 +151,7 @@ : search_answer_container_view_( new SearchAnswerContainerView(view_delegate)) { AddChildView(search_answer_container_view_); - SetLayoutManager(new views::FillLayout); + SetLayoutManager(std::make_unique<views::FillLayout>()); } SearchResultAnswerCardView::~SearchResultAnswerCardView() {}
diff --git a/ui/app_list/views/search_result_list_view.cc b/ui/app_list/views/search_result_list_view.cc index 598a290..b7058add 100644 --- a/ui/app_list/views/search_result_list_view.cc +++ b/ui/app_list/views/search_result_list_view.cc
@@ -41,7 +41,7 @@ results_container_(new views::View), auto_launch_indicator_(new views::View) { results_container_->SetLayoutManager( - new views::BoxLayout(views::BoxLayout::kVertical)); + std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); for (int i = 0; i < kMaxResults; ++i) results_container_->AddChildView(new SearchResultView(this));
diff --git a/ui/app_list/views/search_result_page_view.cc b/ui/app_list/views/search_result_page_view.cc index b095558..25ce3ab 100644 --- a/ui/app_list/views/search_result_page_view.cc +++ b/ui/app_list/views/search_result_page_view.cc
@@ -52,7 +52,7 @@ class SearchCardView : public views::View { public: explicit SearchCardView(views::View* content_view) { - SetLayoutManager(new views::FillLayout()); + SetLayoutManager(std::make_unique<views::FillLayout>()); AddChildView(content_view); } @@ -145,8 +145,8 @@ contents_view_(new views::View) { SetPaintToLayer(); layer()->SetFillsBoundsOpaquely(false); - contents_view_->SetLayoutManager( - new views::BoxLayout(views::BoxLayout::kVertical, gfx::Insets(), 0)); + contents_view_->SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::kVertical, gfx::Insets(), 0)); // Hides this view behind the search box by using the same color and // background border corner radius. All child views' background should be @@ -167,7 +167,7 @@ scroller->SetBackgroundColor(SK_ColorTRANSPARENT); AddChildView(scroller); - SetLayoutManager(new views::FillLayout); + SetLayoutManager(std::make_unique<views::FillLayout>()); } SearchResultPageView::~SearchResultPageView() = default;
diff --git a/ui/app_list/views/search_result_tile_item_list_view.cc b/ui/app_list/views/search_result_tile_item_list_view.cc index e770df4..b2ed326 100644 --- a/ui/app_list/views/search_result_tile_item_list_view.cc +++ b/ui/app_list/views/search_result_tile_item_list_view.cc
@@ -47,7 +47,7 @@ search_box_(search_box), is_play_store_app_search_enabled_( features::IsPlayStoreAppSearchEnabled()) { - SetLayoutManager(new views::BoxLayout( + SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::kHorizontal, gfx::Insets(kItemListVerticalSpacing, kItemListHorizontalSpacing), kBetweenItemSpacing));
diff --git a/ui/app_list/views/suggestions_container_view.cc b/ui/app_list/views/suggestions_container_view.cc index d624752..07890ae 100644 --- a/ui/app_list/views/suggestions_container_view.cc +++ b/ui/app_list/views/suggestions_container_view.cc
@@ -114,7 +114,7 @@ void SuggestionsContainerView::CreateAppsGrid(int apps_num) { DCHECK(search_result_tile_views_.empty()); views::GridLayout* tiles_layout_manager = - views::GridLayout::CreateAndInstall(this); + SetLayoutManager(std::make_unique<views::GridLayout>(this)); SetLayoutManager(tiles_layout_manager); views::ColumnSet* column_set = tiles_layout_manager->AddColumnSet(0);
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn index 7fda2180..a922322 100644 --- a/ui/aura/BUILD.gn +++ b/ui/aura/BUILD.gn
@@ -363,6 +363,7 @@ "mus/input_method_mus_unittest.cc", "mus/os_exchange_data_provider_mus_unittest.cc", "mus/property_converter_unittest.cc", + "mus/system_input_injector_mus_unittest.cc", "mus/user_activity_forwarder_unittest.cc", "mus/window_port_mus_unittest.cc", "mus/window_tree_client_unittest.cc",
diff --git a/ui/aura/mus/system_input_injector_mus.cc b/ui/aura/mus/system_input_injector_mus.cc index 3a2d55c..7b06280 100644 --- a/ui/aura/mus/system_input_injector_mus.cc +++ b/ui/aura/mus/system_input_injector_mus.cc
@@ -4,12 +4,14 @@ #include "ui/aura/mus/system_input_injector_mus.h" +#include "ui/aura/env.h" #include "ui/aura/mus/window_manager_delegate.h" #include "ui/display/display.h" #include "ui/display/screen.h" #include "ui/events/base_event_utils.h" #include "ui/events/event.h" #include "ui/events/keycodes/keyboard_code_conversion.h" +#include "ui/gfx/geometry/point_conversions.h" namespace aura { @@ -49,19 +51,62 @@ SystemInputInjectorMus::~SystemInputInjectorMus() {} void SystemInputInjectorMus::MoveCursorTo(const gfx::PointF& location) { - // TODO(erg): This appears to never be receiving the events from the remote - // side of the connection. I think this is because it doesn't send mouse - // events before the first paint. - NOTIMPLEMENTED(); + ui::MouseEvent event( + ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(), ui::EventTimeForNow(), + modifiers_.GetModifierFlags(), + /* changed_button_flags */ 0, + ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE)); + event.set_location_f(location); + event.set_root_location_f(location); + + InjectEventAt(ui::PointerEvent(event), gfx::ToRoundedPoint(location)); } void SystemInputInjectorMus::InjectMouseButton(ui::EventFlags button, bool down) { - NOTIMPLEMENTED(); + gfx::Point location = aura::Env::GetInstance()->last_mouse_location(); + + int modifier = ui::MODIFIER_NONE; + switch (button) { + case ui::EF_LEFT_MOUSE_BUTTON: + modifier = ui::MODIFIER_LEFT_MOUSE_BUTTON; + break; + case ui::EF_RIGHT_MOUSE_BUTTON: + modifier = ui::MODIFIER_RIGHT_MOUSE_BUTTON; + break; + case ui::EF_MIDDLE_MOUSE_BUTTON: + modifier = ui::MODIFIER_MIDDLE_MOUSE_BUTTON; + default: + LOG(WARNING) << "Invalid flag: " << button << " for the button parameter"; + return; + } + + int flag = modifiers_.GetEventFlagFromModifier(modifier); + bool was_down = modifiers_.GetModifierFlags() & flag; + modifiers_.UpdateModifier(modifier, down); + down = modifiers_.GetModifierFlags() & flag; + + // Suppress nested clicks. EventModifiers counts presses, we only + // dispatch an event on 0-1 (first press) and 1-0 (last release) transitions. + if (down == was_down) + return; + + ui::MouseEvent event( + down ? ui::ET_MOUSE_PRESSED : ui::ET_MOUSE_RELEASED, location, location, + ui::EventTimeForNow(), modifiers_.GetModifierFlags() | flag, + /* changed_button_flags */ flag, + ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE)); + InjectEventAt(ui::PointerEvent(event), location); } void SystemInputInjectorMus::InjectMouseWheel(int delta_x, int delta_y) { - NOTIMPLEMENTED(); + gfx::Point location = aura::Env::GetInstance()->last_mouse_location(); + + ui::MouseWheelEvent event(gfx::Vector2d(delta_x, delta_y), location, location, + ui::EventTimeForNow(), + modifiers_.GetModifierFlags(), + /* changed_button_flags */ 0); + InjectEventAt(ui::PointerEvent(event), location); } void SystemInputInjectorMus::InjectKeyEvent(ui::DomCode dom_code, @@ -77,22 +122,24 @@ ui::KeyEvent e(down ? ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED, key_code, dom_code, modifiers_.GetModifierFlags()); - // Even when we're dispatching a key event, we need to have a valid display - // for event targeting, so grab the display of where the cursor currently is. + InjectEventAt(e, display::Screen::GetScreen()->GetCursorScreenPoint()); +} + +void SystemInputInjectorMus::InjectEventAt(const ui::Event& event, + const gfx::Point& location) { display::Screen* screen = display::Screen::GetScreen(); - display::Display display = - screen->GetDisplayNearestPoint(screen->GetCursorScreenPoint()); - client_->InjectEvent(e, display.id()); + display::Display display = screen->GetDisplayNearestPoint(location); + client_->InjectEvent(event, display.id()); } void SystemInputInjectorMus::UpdateModifier(unsigned int modifier, bool down) { if (modifier == ui::MODIFIER_NONE) return; - if (modifier == ui::MODIFIER_CAPS_LOCK) - modifiers_.UpdateModifier(ui::MODIFIER_MOD3, down); - else - modifiers_.UpdateModifier(modifier, down); + // KeyboardEvdev performs a transformation here from MODIFIER_CAPS_LOCK to + // MODIFIER_MOD3. That was needed to work around X11, we actually want to + // ship this state across the wire without modification. + modifiers_.UpdateModifier(modifier, down); } } // namespace aura
diff --git a/ui/aura/mus/system_input_injector_mus.h b/ui/aura/mus/system_input_injector_mus.h index e1306f3..6f3e2ef 100644 --- a/ui/aura/mus/system_input_injector_mus.h +++ b/ui/aura/mus/system_input_injector_mus.h
@@ -5,6 +5,7 @@ #ifndef UI_AURA_MUS_SYSTEM_INPUT_INJECTOR_MUS_H_ #define UI_AURA_MUS_SYSTEM_INPUT_INJECTOR_MUS_H_ +#include "ui/aura/aura_export.h" #include "ui/events/event_modifiers.h" #include "ui/events/system_input_injector.h" @@ -12,7 +13,7 @@ class WindowManagerClient; -class SystemInputInjectorMus : public ui::SystemInputInjector { +class AURA_EXPORT SystemInputInjectorMus : public ui::SystemInputInjector { public: explicit SystemInputInjectorMus(WindowManagerClient* client); ~SystemInputInjectorMus() override; @@ -26,6 +27,9 @@ bool suppress_auto_repeat) override; private: + // Forwards |event| to the display at |location|. + void InjectEventAt(const ui::Event& event, const gfx::Point& location); + // Updates |modifiers_| based on an incoming event. void UpdateModifier(unsigned int modifier, bool down);
diff --git a/ui/aura/mus/system_input_injector_mus_unittest.cc b/ui/aura/mus/system_input_injector_mus_unittest.cc new file mode 100644 index 0000000..04543f9a --- /dev/null +++ b/ui/aura/mus/system_input_injector_mus_unittest.cc
@@ -0,0 +1,150 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/aura/mus/system_input_injector_mus.h" + +#include <vector> + +#include "ui/aura/mus/window_manager_delegate.h" +#include "ui/aura/mus/window_tree_host_mus_init_params.h" +#include "ui/aura/test/aura_test_base.h" +#include "ui/events/event.h" +#include "ui/events/keycodes/dom/dom_code.h" +#include "ui/events/keycodes/keyboard_codes.h" + +namespace aura { + +class TestDispaterchWindowManagerClient : public aura::WindowManagerClient { + public: + TestDispaterchWindowManagerClient() {} + ~TestDispaterchWindowManagerClient() override {} + + const std::vector<std::unique_ptr<ui::Event>>& events() const { + return events_; + } + + // This is the one method in this interface that we're using to grab data. + void InjectEvent(const ui::Event& event, int64_t display_id) override { + events_.push_back(ui::Event::Clone(event)); + } + + // The rest of these interfaces aren't relevant to testing + // SystemInputInjectorMus and are left empty. + void SetFrameDecorationValues( + ui::mojom::FrameDecorationValuesPtr values) override {} + void SetNonClientCursor(Window* window, + const ui::CursorData& non_client_cursor) override {} + void AddAccelerators(std::vector<ui::mojom::WmAcceleratorPtr> accelerators, + const base::Callback<void(bool)>& callback) override {} + void RemoveAccelerator(uint32_t id) override {} + void AddActivationParent(Window* window) override {} + void RemoveActivationParent(Window* window) override {} + void SetExtendedHitRegionForChildren(Window* window, + const gfx::Insets& mouse_area, + const gfx::Insets& touch_area) override { + } + void LockCursor() override {} + void UnlockCursor() override {} + void SetCursorVisible(bool visible) override {} + void SetCursorSize(ui::CursorSize cursor_size) override {} + void SetGlobalOverrideCursor(base::Optional<ui::CursorData> cursor) override { + } + void SetCursorTouchVisible(bool enabled) override {} + void SetKeyEventsThatDontHideCursor( + std::vector<ui::mojom::EventMatcherPtr> cursor_key_list) override {} + void RequestClose(Window* window) override {} + void SetBlockingContainers( + const std::vector<BlockingContainers>& all_blocking_containers) override { + } + bool WaitForInitialDisplays() override { return false; } + WindowTreeHostMusInitParams CreateInitParamsForNewDisplay() override { + return WindowTreeHostMusInitParams(); + } + void SetDisplayConfiguration( + const std::vector<display::Display>& displays, + std::vector<ui::mojom::WmViewportMetricsPtr> viewport_metrics, + int64_t primary_display_id, + const std::vector<display::Display>& mirrors) override {} + void AddDisplayReusingWindowTreeHost( + WindowTreeHostMus* window_tree_host, + const display::Display& display, + ui::mojom::WmViewportMetricsPtr viewport_metrics) override {} + void SwapDisplayRoots(WindowTreeHostMus* window_tree_host1, + WindowTreeHostMus* window_tree_host2) override {} + + private: + std::vector<std::unique_ptr<ui::Event>> events_; + + DISALLOW_COPY_AND_ASSIGN(TestDispaterchWindowManagerClient); +}; + +class SystemInputInjectorMusTest : public test::AuraTestBase { + protected: + SystemInputInjectorMusTest() {} + ~SystemInputInjectorMusTest() override {} + + const std::vector<std::unique_ptr<ui::Event>>& events() const { + return window_manager_client_.events(); + } + + SystemInputInjectorMus* injector() { return input_injector_.get(); } + + void SetUp() override { + test::AuraTestBase::SetUp(); + input_injector_ = + std::make_unique<SystemInputInjectorMus>(&window_manager_client_); + } + + void TearDown() override { + input_injector_.reset(); + test::AuraTestBase::TearDown(); + } + + private: + TestDispaterchWindowManagerClient window_manager_client_; + std::unique_ptr<SystemInputInjectorMus> input_injector_; + + DISALLOW_COPY_AND_ASSIGN(SystemInputInjectorMusTest); +}; + +TEST_F(SystemInputInjectorMusTest, MouseMove) { + injector()->MoveCursorTo(gfx::PointF(40, 45)); + + ASSERT_EQ(1u, events().size()); + ASSERT_EQ(ui::ET_POINTER_MOVED, events()[0]->type()); + EXPECT_EQ(gfx::Point(40, 45), events()[0]->AsPointerEvent()->location()); +} + +TEST_F(SystemInputInjectorMusTest, ModifierKeys) { + injector()->InjectKeyEvent(ui::DomCode::CONTROL_LEFT, true, true); + injector()->InjectKeyEvent(ui::DomCode::US_T, true, true); + + ASSERT_EQ(2u, events().size()); + ASSERT_EQ(ui::ET_KEY_PRESSED, events()[1]->type()); + // Verify that we have the right modifier on the event. + EXPECT_TRUE(events()[1]->IsControlDown()); + EXPECT_EQ(ui::VKEY_T, events()[1]->AsKeyEvent()->key_code()); +} + +TEST_F(SystemInputInjectorMusTest, MouseButton) { + injector()->InjectKeyEvent(ui::DomCode::CONTROL_LEFT, true, true); + injector()->InjectMouseButton(ui::EF_LEFT_MOUSE_BUTTON, true); + + // Verify that this is a ctrl+click. + ASSERT_EQ(2u, events().size()); + ASSERT_EQ(ui::ET_POINTER_DOWN, events()[1]->type()); + EXPECT_TRUE(events()[1]->IsControlDown()); + EXPECT_TRUE(ui::EF_LEFT_MOUSE_BUTTON & events()[1]->flags()); +} + +TEST_F(SystemInputInjectorMusTest, MouseWheel) { + injector()->InjectMouseWheel(0, 20); + + ASSERT_EQ(1u, events().size()); + ASSERT_EQ(ui::ET_POINTER_WHEEL_CHANGED, events()[0]->type()); + EXPECT_EQ(gfx::Vector2d(0, 20), + events()[0]->AsPointerEvent()->pointer_details().offset); +} + +} // namespace aura
diff --git a/ui/base/l10n/l10n_util.cc b/ui/base/l10n/l10n_util.cc index aa8139b6..35b202f 100644 --- a/ui/base/l10n/l10n_util.cc +++ b/ui/base/l10n/l10n_util.cc
@@ -210,8 +210,10 @@ // Returns true if |locale_name| has an alias in the ICU data file. bool IsDuplicateName(const std::string& locale_name) { static const char* const kDuplicateNames[] = { + "ar_001", "en", "en_001", + "en_150", "pt", // pt-BR and pt-PT are used. "zh", "zh_hans_cn",
diff --git a/ui/base/mojo/DEPS b/ui/base/mojo/DEPS index 16764a92..4c418e2 100644 --- a/ui/base/mojo/DEPS +++ b/ui/base/mojo/DEPS
@@ -1,3 +1,4 @@ include_rules = [ "+mojo/public/cpp/bindings", + "+third_party/WebKit/common/clipboard/clipboard.mojom-shared.h" ]
diff --git a/ui/base/mojo/clipboard.typemap b/ui/base/mojo/clipboard.typemap new file mode 100644 index 0000000..1063cb36 --- /dev/null +++ b/ui/base/mojo/clipboard.typemap
@@ -0,0 +1,11 @@ +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +mojom = "//third_party/WebKit/common/clipboard/clipboard.mojom" +public_headers = [ "//ui/base/clipboard/clipboard_types.h" ] +traits_headers = [ "//ui/base/mojo/clipboard_struct_traits.h" ] +deps = [ + "//ui/base", +] +type_mappings = [ "blink.mojom.ClipboardBuffer=ui::ClipboardType" ]
diff --git a/ui/base/mojo/clipboard_struct_traits.h b/ui/base/mojo/clipboard_struct_traits.h new file mode 100644 index 0000000..81c618e --- /dev/null +++ b/ui/base/mojo/clipboard_struct_traits.h
@@ -0,0 +1,42 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_BASE_MOJO_CLIPBOARD_STRUCT_TRAITS_H_ +#define UI_BASE_MOJO_CLIPBOARD_STRUCT_TRAITS_H_ + +#include "third_party/WebKit/common/clipboard/clipboard.mojom-shared.h" +#include "ui/base/clipboard/clipboard_types.h" + +namespace mojo { + +template <> +struct EnumTraits<blink::mojom::ClipboardBuffer, ui::ClipboardType> { + static blink::mojom::ClipboardBuffer ToMojom(ui::ClipboardType) { + // We never intend on converting from ui::Clipboardtype to + // blink::mojom::ClipboardBuffer. + NOTREACHED(); + return blink::mojom::ClipboardBuffer::kStandard; + } + + static bool FromMojom(blink::mojom::ClipboardBuffer clipboard_type, + ui::ClipboardType* out) { + switch (clipboard_type) { + case blink::mojom::ClipboardBuffer::kStandard: + *out = ui::CLIPBOARD_TYPE_COPY_PASTE; + return true; + case blink::mojom::ClipboardBuffer::kSelection: +#if defined(USE_X11) + *out = ui::CLIPBOARD_TYPE_SELECTION; + return true; +#else + return false; +#endif + } + return false; + } +}; + +} // namespace mojo + +#endif // UI_BASE_MOJO_CLIPBOARD_STRUCT_TRAITS_H_
diff --git a/ui/base/mojo/typemaps.gni b/ui/base/mojo/typemaps.gni index 2d3c3c14..45a6bcc 100644 --- a/ui/base/mojo/typemaps.gni +++ b/ui/base/mojo/typemaps.gni
@@ -3,6 +3,7 @@ # found in the LICENSE file. typemaps = [ + "//ui/base/mojo/clipboard.typemap", "//ui/base/mojo/ui_base_types.typemap", "//ui/base/mojo/window_open_disposition.typemap", ]
diff --git a/ui/chromeos/ime/candidate_view_unittest.cc b/ui/chromeos/ime/candidate_view_unittest.cc index 26dcf638..cc6c716 100644 --- a/ui/chromeos/ime/candidate_view_unittest.cc +++ b/ui/chromeos/ime/candidate_view_unittest.cc
@@ -46,7 +46,7 @@ container_ = init_params.delegate->GetContentsView(); container_->SetLayoutManager( - new views::BoxLayout(views::BoxLayout::kVertical)); + std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); for (size_t i = 0; i < arraysize(kDummyCandidates); ++i) { CandidateView* candidate = new CandidateView( this, ui::CandidateWindow::VERTICAL);
diff --git a/ui/chromeos/ime/candidate_window_view.cc b/ui/chromeos/ime/candidate_window_view.cc index b4ac5a27..e2f993a 100644 --- a/ui/chromeos/ime/candidate_window_view.cc +++ b/ui/chromeos/ime/candidate_window_view.cc
@@ -110,7 +110,7 @@ label_->SetHorizontalAlignment(align); label_->SetBorder(views::CreateEmptyBorder(2, 2, 2, 4)); - SetLayoutManager(new views::FillLayout()); + SetLayoutManager(std::make_unique<views::FillLayout>()); AddChildView(label_); SetBackground(views::CreateSolidBackground( color_utils::AlphaBlend(SK_ColorBLACK, @@ -166,7 +166,8 @@ 1, GetNativeTheme()->GetSystemColor( ui::NativeTheme::kColorId_MenuBorderColor))); - SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical)); + SetLayoutManager( + std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); auxiliary_text_ = new InformationTextArea(gfx::ALIGN_RIGHT, 0); preedit_ = new InformationTextArea(gfx::ALIGN_LEFT, kMinPreeditAreaWidth); candidate_area_ = new views::View; @@ -180,7 +181,7 @@ AddChildView(auxiliary_text_); auxiliary_text_->SetBorderFromPosition(InformationTextArea::TOP); candidate_area_->SetLayoutManager( - new views::BoxLayout(views::BoxLayout::kVertical)); + std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); } else { AddChildView(preedit_); AddChildView(auxiliary_text_); @@ -188,7 +189,7 @@ auxiliary_text_->SetAlignment(gfx::ALIGN_LEFT); auxiliary_text_->SetBorderFromPosition(InformationTextArea::BOTTOM); candidate_area_->SetLayoutManager( - new views::BoxLayout(views::BoxLayout::kHorizontal)); + std::make_unique<views::BoxLayout>(views::BoxLayout::kHorizontal)); } } @@ -255,13 +256,13 @@ auxiliary_text_->SetAlignment(gfx::ALIGN_RIGHT); auxiliary_text_->SetBorderFromPosition(InformationTextArea::TOP); candidate_area_->SetLayoutManager( - new views::BoxLayout(views::BoxLayout::kVertical)); + std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); } else { ReorderChildView(auxiliary_text_, 1); auxiliary_text_->SetAlignment(gfx::ALIGN_LEFT); auxiliary_text_->SetBorderFromPosition(InformationTextArea::BOTTOM); candidate_area_->SetLayoutManager( - new views::BoxLayout(views::BoxLayout::kHorizontal)); + std::make_unique<views::BoxLayout>(views::BoxLayout::kHorizontal)); } }
diff --git a/ui/chromeos/ime/infolist_window.cc b/ui/chromeos/ime/infolist_window.cc index d1f1389..91fef0f 100644 --- a/ui/chromeos/ime/infolist_window.cc +++ b/ui/chromeos/ime/infolist_window.cc
@@ -117,7 +117,8 @@ const gfx::FontList& title_font_list, const gfx::FontList& description_font_list) : entry_(entry) { - SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical)); + SetLayoutManager( + std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); title_label_ = new views::Label(entry.title, {title_font_list}); title_label_->SetPosition(gfx::Point(0, 0)); @@ -185,7 +186,8 @@ 1, GetNativeTheme()->GetSystemColor( ui::NativeTheme::kColorId_MenuBorderColor))); - SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical)); + SetLayoutManager( + std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); views::Label* caption_label = new views::Label( l10n_util::GetStringUTF16(IDS_CHROMEOS_IME_INFOLIST_WINDOW_TITLE));
diff --git a/ui/chromeos/ime/mode_indicator_view.cc b/ui/chromeos/ime/mode_indicator_view.cc index ed78f54..d12e5ec 100644 --- a/ui/chromeos/ime/mode_indicator_view.cc +++ b/ui/chromeos/ime/mode_indicator_view.cc
@@ -91,7 +91,7 @@ } void ModeIndicatorView::Init() { - SetLayoutManager(new views::FillLayout()); + SetLayoutManager(std::make_unique<views::FillLayout>()); AddChildView(label_view_); SetAnchorRect(cursor_bounds_);
diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc index 6fb94ea..c344067f4 100644 --- a/ui/compositor/test/in_process_context_factory.cc +++ b/ui/compositor/test/in_process_context_factory.cc
@@ -98,11 +98,8 @@ context_provider_->ContextSupport()->Swap(); } gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); - const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM(); - gl->ShallowFlushCHROMIUM(); - gpu::SyncToken sync_token; - gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); + gl->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData()); context_provider_->ContextSupport()->SignalSyncToken( sync_token, base::Bind(&DirectOutputSurface::OnSwapBuffersComplete,
diff --git a/ui/display/display_layout.h b/ui/display/display_layout.h index f9f8c46..9a59d32f 100644 --- a/ui/display/display_layout.h +++ b/ui/display/display_layout.h
@@ -100,6 +100,7 @@ std::vector<DisplayPlacement> placement_list; + // TODO(crbug.com/791881) Remove this variable and related code. // True if displays are mirrored. bool mirrored;
diff --git a/ui/display/manager/chromeos/display_change_observer.cc b/ui/display/manager/chromeos/display_change_observer.cc index 692479cb..79bfc80 100644 --- a/ui/display/manager/chromeos/display_change_observer.cc +++ b/ui/display/manager/chromeos/display_change_observer.cc
@@ -157,9 +157,9 @@ [](const DisplaySnapshot* display_state) { return display_state->display_id(); }); - bool mirrored = display_manager_->layout_store()->GetMirrorMode(list); - return mirrored ? MULTIPLE_DISPLAY_STATE_DUAL_MIRROR - : MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED; + return display_manager_->ShouldSetMirrorModeOn(list) + ? MULTIPLE_DISPLAY_STATE_DUAL_MIRROR + : MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED; } bool DisplayChangeObserver::GetResolutionForDisplayId(int64_t display_id,
diff --git a/ui/display/manager/chromeos/display_configurator.cc b/ui/display/manager/chromeos/display_configurator.cc index 20f58d42..6e4e4f8a 100644 --- a/ui/display/manager/chromeos/display_configurator.cc +++ b/ui/display/manager/chromeos/display_configurator.cc
@@ -999,6 +999,8 @@ this, &DisplayConfigurator::ConfigureDisplays); } + // TODO(crbug.com/794831): Solve the issue of mirror mode on display resume. + // If requested_power_state_ is ALL_OFF due to idle suspend, powerd will turn // the display power on when it enables the backlight. SetDisplayPower(requested_power_state_, kSetDisplayPowerNoFlags,
diff --git a/ui/display/manager/display_layout_store.h b/ui/display/manager/display_layout_store.h index 6dcead3..d8243b3 100644 --- a/ui/display/manager/display_layout_store.h +++ b/ui/display/manager/display_layout_store.h
@@ -25,6 +25,8 @@ // Set true to force mirror mode. void set_forced_mirror_mode(bool forced) { forced_mirror_mode_ = forced; } + bool forced_mirror_mode() const { return forced_mirror_mode_; } + void SetDefaultDisplayPlacement(const DisplayPlacement& placement); // Registers the display layout info for the specified display(s).
diff --git a/ui/display/manager/display_manager.cc b/ui/display/manager/display_manager.cc index 4a0caf9..3940ca5 100644 --- a/ui/display/manager/display_manager.cc +++ b/ui/display/manager/display_manager.cc
@@ -300,10 +300,6 @@ info_list.back().set_native(true); } MaybeInitInternalDisplay(&info_list[0]); - if (info_list.size() > 1 && - command_line->HasSwitch(::switches::kEnableSoftwareMirroring)) { - SetMultiDisplayMode(MIRRORING); - } OnNativeDisplaysChanged(info_list); return true; } @@ -723,8 +719,8 @@ std::map<gfx::Point, int64_t> origins; bool internal_display_connected = false; - num_connected_displays_ = updated_displays.size(); - ClearMirroringSourceAndDestination(); + DisplayIdList hardware_mirroring_display_id_list; + int64_t mirroring_source_id = kInvalidDisplayId; DisplayInfoList new_display_info_list; for (const auto& display_info : updated_displays) { if (!internal_display_connected) @@ -735,17 +731,17 @@ const auto iter = origins.find(origin); if (iter != origins.end()) { InsertAndUpdateDisplayInfo(display_info); - if (hardware_mirroring_display_id_list_.empty()) { + if (hardware_mirroring_display_id_list.empty()) { // Unlike software mirroring, hardware mirroring has no source and // target. All mirroring displays scan the same frame buffer. But for // convenience, we treat the first mirroring display as source. - mirroring_source_id_ = iter->second; + mirroring_source_id = iter->second; } // Only keep the first hardware mirroring display in // |new_display_info_list| because hardware mirroring is not visible for // display manager and all hardware mirroring displays should be treated // as one single display from this point. - hardware_mirroring_display_id_list_.emplace_back(display_info.id()); + hardware_mirroring_display_id_list.emplace_back(display_info.id()); } else { origins.emplace(origin, display_info.id()); new_display_info_list.emplace_back(display_info); @@ -791,20 +787,31 @@ } #if defined(OS_CHROMEOS) - if (!configure_displays_ && new_display_info_list.size() > 1) { + if (!configure_displays_ && new_display_info_list.size() > 1 && + hardware_mirroring_display_id_list.empty()) { + // Mirror mode is set by DisplayConfigurator on the device. Emulate it when + // running on linux desktop. Do not emulate it when hardware mirroring is + // on (This only happens in test). DisplayIdList list = GenerateDisplayIdList( new_display_info_list.begin(), new_display_info_list.end(), - [](const ManagedDisplayInfo& info) { return info.id(); }); - - const DisplayLayout& layout = - layout_store_->GetRegisteredDisplayLayout(list); - // Mirror mode is set by DisplayConfigurator on the device. - // Emulate it when running on linux desktop. - if (layout.mirrored) - SetMultiDisplayMode(MIRRORING); + [](const ManagedDisplayInfo& display_info) { + return display_info.id(); + }); + multi_display_mode_ = (base::CommandLine::ForCurrentProcess()->HasSwitch( + ::switches::kEnableSoftwareMirroring) || + ShouldSetMirrorModeOn(list)) + ? MIRRORING + : EXTENDED; } #endif + // Do not clear current mirror state before calling ShouldSetMirrorModeOn() + // as it depends on the state. + software_mirroring_display_list_.clear(); + hardware_mirroring_display_id_list_ = hardware_mirroring_display_id_list; + mirroring_source_id_ = mirroring_source_id; + num_connected_displays_ = updated_displays.size(); + UpdateDisplaysWith(new_display_info_list); } @@ -1022,6 +1029,8 @@ if (delegate_ && primary_metrics) NotifyMetricsChanged(screen_->GetPrimaryDisplay(), primary_metrics); + UpdateInfoForRestoringMirrorMode(); + if (delegate_) delegate_->PostDisplayConfigurationChange(); @@ -1175,6 +1184,32 @@ : kInvalidDisplayId; } +bool DisplayManager::ShouldSetMirrorModeOn(const DisplayIdList& new_id_list) { + DCHECK(new_id_list.size() > 1); + if (layout_store_->forced_mirror_mode()) + return true; + + if (disable_restoring_mirror_mode_for_test_) + return false; + + if (num_connected_displays_ <= 1) { + // The ChromeOS just boots up or it only has one display. Restore mirror + // mode based on the external displays' mirror info stored in the + // preferences. Mirror mode should be on if one of the external displays was + // in mirror mode before. + for (int64_t id : new_id_list) { + if (external_display_mirror_info_.count( + GetDisplayIdWithoutOutputIndex(id))) { + return true; + } + } + return false; + } + // Mirror mode should remain unchanged as long as there are more than one + // connected displays. + return IsInMirrorMode(); +} + void DisplayManager::SetMirrorMode(bool mirror) { if ((is_multi_mirroring_enabled_ && num_connected_displays() < 2) || (!is_multi_mirroring_enabled_ && num_connected_displays() != 2)) { @@ -1912,4 +1947,21 @@ : GetDisplayAt(0); } +void DisplayManager::UpdateInfoForRestoringMirrorMode() { + if (num_connected_displays_ <= 1) + return; + + for (auto id : GetCurrentDisplayIdList()) { + if (Display::IsInternalDisplayId(id)) + continue; + // Mask the output index out (8 bits) so that the user does not have to + // reconnect a display to the same port to restore mirror mode. + int64_t masked_id = GetDisplayIdWithoutOutputIndex(id); + if (IsInMirrorMode()) + external_display_mirror_info_.emplace(masked_id); + else + external_display_mirror_info_.erase(masked_id); + } +} + } // namespace display
diff --git a/ui/display/manager/display_manager.h b/ui/display/manager/display_manager.h index 8058986..386c79c2 100644 --- a/ui/display/manager/display_manager.h +++ b/ui/display/manager/display_manager.h
@@ -321,6 +321,20 @@ return software_mirroring_display_list_; } + // Used in test to prevent previous mirror modes affecting current mode. + void set_disable_restoring_mirror_mode_for_test(bool disabled) { + disable_restoring_mirror_mode_for_test_ = disabled; + } + + const std::set<int64_t>& external_display_mirror_info() const { + return external_display_mirror_info_; + } + + void set_external_display_mirror_info( + const std::set<int64_t>& external_display_mirror_info) { + external_display_mirror_info_ = external_display_mirror_info; + } + // Remove mirroring source and destination displays, so that they will be // updated when UpdateDisplaysWith() is called. void ClearMirroringSourceAndDestination(); @@ -366,6 +380,9 @@ // the first display ID. int64_t GetDisplayIdForUIScaling() const; + // Returns true if mirror mode should be set on for the specified displays. + bool ShouldSetMirrorModeOn(const DisplayIdList& id_list); + // Change the mirror mode. void SetMirrorMode(bool mirrored); @@ -502,6 +519,9 @@ Displays* display_list, std::vector<int64_t>* updated_ids); + // Update the info used to restore mirror mode. + void UpdateInfoForRestoringMirrorMode(); + Delegate* delegate_ = nullptr; // not owned. // When set to true, DisplayManager will use DisplayConfigurator to configure @@ -574,6 +594,12 @@ // destination and store their ids in this list. DisplayIdList hardware_mirroring_display_id_list_; + // Stores external displays that were in mirror mode before. + std::set<int64_t> external_display_mirror_info_; + + // True if mirror mode should not be restored. Only used in test. + bool disable_restoring_mirror_mode_for_test_ = false; + // Cached mirror mode for metrics changed notification. bool mirror_mode_for_metrics_ = false;
diff --git a/ui/display/manager/display_manager_utilities.cc b/ui/display/manager/display_manager_utilities.cc index 5f6551dd..9220917 100644 --- a/ui/display/manager/display_manager_utilities.cc +++ b/ui/display/manager/display_manager_utilities.cc
@@ -7,6 +7,7 @@ #include <algorithm> #include "base/command_line.h" +#include "base/strings/string_number_conversions.h" #include "base/sys_info.h" #include "ui/display/display_switches.h" #include "ui/display/manager/managed_display_info.h" @@ -268,4 +269,16 @@ return s.str(); } +display::ManagedDisplayInfo CreateDisplayInfo(int64_t id, + const gfx::Rect& bounds) { + display::ManagedDisplayInfo info(id, "x-" + base::Int64ToString(id), false); + info.SetBounds(bounds); + return info; +} + +int64_t GetDisplayIdWithoutOutputIndex(int64_t id) { + constexpr uint64_t kMask = ~static_cast<uint64_t>(0xFF); + return static_cast<int64_t>(kMask & id); +} + } // namespace display
diff --git a/ui/display/manager/display_manager_utilities.h b/ui/display/manager/display_manager_utilities.h index eb7abf09..fd0746a 100644 --- a/ui/display/manager/display_manager_utilities.h +++ b/ui/display/manager/display_manager_utilities.h
@@ -89,6 +89,14 @@ DISPLAY_MANAGER_EXPORT std::string DisplayIdListToString( const DisplayIdList& list); +// Creates managed display info. +DISPLAY_MANAGER_EXPORT display::ManagedDisplayInfo CreateDisplayInfo( + int64_t id, + const gfx::Rect& bounds); + +// Get the display id after the output index (8 bits) is masked out. +DISPLAY_MANAGER_EXPORT int64_t GetDisplayIdWithoutOutputIndex(int64_t id); + } // namespace display #endif // UI_DISPLAY_MANAGER_DISPLAY_MANAGER_UTILITIES_H_
diff --git a/ui/display/types/display_constants.h b/ui/display/types/display_constants.h index e8224e1..7ef274f 100644 --- a/ui/display/types/display_constants.h +++ b/ui/display/types/display_constants.h
@@ -21,7 +21,7 @@ MULTIPLE_DISPLAY_STATE_INVALID, MULTIPLE_DISPLAY_STATE_HEADLESS, MULTIPLE_DISPLAY_STATE_SINGLE, - MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, + MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, // TODO(crbug.com/774795) Rename this. MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED, // 2+ displays in extended mode. };
diff --git a/ui/events/blink/DEPS b/ui/events/blink/DEPS index f2167380..b1228dde 100644 --- a/ui/events/blink/DEPS +++ b/ui/events/blink/DEPS
@@ -15,7 +15,7 @@ "+third_party/WebKit/public/platform/WebMouseWheelEvent.h", "+third_party/WebKit/public/platform/WebPoint.h", "+third_party/WebKit/public/platform/WebTouchEvent.h", - "+third_party/WebKit/public/web/WebActiveWheelFlingParameters.h", + "+third_party/WebKit/public/web/WebActiveFlingParameters.h", "+ui/display/win", "+ui/gfx",
diff --git a/ui/events/blink/blink_event_util.cc b/ui/events/blink/blink_event_util.cc index bf500b4..6c253aa 100644 --- a/ui/events/blink/blink_event_util.cc +++ b/ui/events/blink/blink_event_util.cc
@@ -280,14 +280,12 @@ if (event.has_synthetic_phase != event_to_coalesce.has_synthetic_phase) return false; + if (event.phase == event_to_coalesce.phase && + event.momentum_phase == event_to_coalesce.momentum_phase) { + return true; + } + if (event.has_synthetic_phase) { - // Wheel events with synthetic phase information don't have momentum_phase. - DCHECK_EQ(WebMouseWheelEvent::kPhaseNone, event.momentum_phase); - DCHECK_EQ(WebMouseWheelEvent::kPhaseNone, event_to_coalesce.momentum_phase); - - if (event.phase == event_to_coalesce.phase) - return true; - // Synthetic phase information is added based on a timer in // MouseWheelPhaseHandler. This information is for simulating scroll // sequences when the beginning and end of scrolls are not available. It is @@ -300,10 +298,8 @@ event_to_coalesce.phase == WebMouseWheelEvent::kPhaseBegan) || (event.phase == WebMouseWheelEvent::kPhaseBegan && event_to_coalesce.phase == WebMouseWheelEvent::kPhaseChanged); - } else { - return event.phase == event_to_coalesce.phase && - event.momentum_phase == event_to_coalesce.momentum_phase; } + return false; } bool CanCoalesce(const WebMouseWheelEvent& event_to_coalesce,
diff --git a/ui/events/blink/fling_booster.cc b/ui/events/blink/fling_booster.cc index 04bc1ef8..233d720 100644 --- a/ui/events/blink/fling_booster.cc +++ b/ui/events/blink/fling_booster.cc
@@ -76,6 +76,13 @@ return true; case WebInputEvent::kGestureScrollUpdate: { + if (gesture_event.data.scroll_update.inertial_phase == + WebGestureEvent::kMomentumPhase) { + // GSU events in momentum phase are generated by FlingController to + // progress fling and should not interfere with fling boosting. + return false; + } + if (ShouldSuppressScrollForFlingBoosting(gesture_event)) { ExtendBoostedFlingTimeout(gesture_event); return true;
diff --git a/ui/events/blink/input_handler_proxy.cc b/ui/events/blink/input_handler_proxy.cc index d488b872..9d657c7 100644 --- a/ui/events/blink/input_handler_proxy.cc +++ b/ui/events/blink/input_handler_proxy.cc
@@ -655,121 +655,6 @@ return result; } -InputHandlerProxy::EventDisposition InputHandlerProxy::FlingScrollByMouseWheel( - const WebMouseWheelEvent& wheel_event, - cc::EventListenerProperties listener_properties) { - DCHECK(listener_properties == cc::EventListenerProperties::kPassive || - listener_properties == cc::EventListenerProperties::kNone); - - DCHECK(!wheel_event.rails_mode); - gfx::Vector2dF scroll_delta(-wheel_event.delta_x, -wheel_event.delta_y); - - DCHECK(!wheel_event.scroll_by_page); - DCHECK(wheel_event.has_precise_scrolling_deltas); - if (touchpad_and_wheel_scroll_latching_enabled_) { - if (gesture_scroll_on_impl_thread_) { - TRACE_EVENT_INSTANT2("input", - "InputHandlerProxy::handle_input wheel scroll", - TRACE_EVENT_SCOPE_THREAD, "deltaX", scroll_delta.x(), - "deltaY", scroll_delta.y()); - - cc::ScrollStateData scroll_state_update_data; - scroll_state_update_data.delta_x = scroll_delta.x(); - scroll_state_update_data.delta_y = scroll_delta.y(); - scroll_state_update_data.position_x = wheel_event.PositionInWidget().x; - scroll_state_update_data.position_y = wheel_event.PositionInWidget().y; - cc::ScrollState scroll_state_update(scroll_state_update_data); - - cc::InputHandlerScrollResult scroll_result = - input_handler_->ScrollBy(&scroll_state_update); - - if (!scroll_result.did_scroll && - input_handler_->ScrollingShouldSwitchtoMainThread()) { - gesture_scroll_on_impl_thread_ = false; - return DID_NOT_HANDLE; - } - - HandleOverscroll(gfx::Point(wheel_event.PositionInWidget().x, - wheel_event.PositionInWidget().y), - scroll_result, false); - if (scroll_result.did_scroll) { - return listener_properties == cc::EventListenerProperties::kPassive - ? DID_HANDLE_NON_BLOCKING - : DID_HANDLE; - } - - return DROP_EVENT; - } else { - return DID_NOT_HANDLE; - } - } else { // !touchpad_and_wheel_scroll_latching_enabled_ - cc::ScrollStateData scroll_state_begin_data; - scroll_state_begin_data.position_x = wheel_event.PositionInWidget().x; - scroll_state_begin_data.position_y = wheel_event.PositionInWidget().y; - scroll_state_begin_data.is_beginning = true; - cc::ScrollState scroll_state_begin(scroll_state_begin_data); - cc::InputHandler::ScrollStatus scroll_status = input_handler_->ScrollBegin( - &scroll_state_begin, cc::InputHandler::WHEEL); - - RecordMainThreadScrollingReasons( - blink::kWebGestureDeviceTouchpad, - scroll_status.main_thread_scrolling_reasons); - - mouse_wheel_result_ = - (listener_properties == cc::EventListenerProperties::kPassive) - ? DID_HANDLE_NON_BLOCKING - : DROP_EVENT; - RecordScrollingThreadStatus(blink::kWebGestureDeviceTouchpad, - scroll_status.main_thread_scrolling_reasons); - - switch (scroll_status.thread) { - case cc::InputHandler::SCROLL_ON_IMPL_THREAD: { - TRACE_EVENT_INSTANT2("input", - "InputHandlerProxy::handle_input wheel scroll", - TRACE_EVENT_SCOPE_THREAD, "deltaX", - scroll_delta.x(), "deltaY", scroll_delta.y()); - - cc::ScrollStateData scroll_state_update_data; - scroll_state_update_data.delta_x = scroll_delta.x(); - scroll_state_update_data.delta_y = scroll_delta.y(); - scroll_state_update_data.position_x = wheel_event.PositionInWidget().x; - scroll_state_update_data.position_y = wheel_event.PositionInWidget().y; - cc::ScrollState scroll_state_update(scroll_state_update_data); - - cc::InputHandlerScrollResult scroll_result = - input_handler_->ScrollBy(&scroll_state_update); - HandleOverscroll(gfx::Point(wheel_event.PositionInWidget().x, - wheel_event.PositionInWidget().y), - scroll_result, false); - - cc::ScrollStateData scroll_state_end_data; - scroll_state_end_data.is_ending = true; - cc::ScrollState scroll_state_end(scroll_state_end_data); - input_handler_->ScrollEnd(&scroll_state_end); - - if (scroll_result.did_scroll) { - return listener_properties == cc::EventListenerProperties::kPassive - ? DID_HANDLE_NON_BLOCKING - : DID_HANDLE; - } - return DROP_EVENT; - } - case cc::InputHandler::SCROLL_IGNORED: - // TODO(jamesr): This should be DROP_EVENT, but in cases where we fail - // to properly sync scrollability it's safer to send the event to the - // main thread. Change back to DROP_EVENT once we have synchronization - // bugs sorted out. - return DID_NOT_HANDLE; - case cc::InputHandler::SCROLL_UNKNOWN: - case cc::InputHandler::SCROLL_ON_MAIN_THREAD: - return DID_NOT_HANDLE; - default: - NOTREACHED(); - return DID_NOT_HANDLE; - } - } -} - InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureScrollBegin( const WebGestureEvent& gesture_event) { if (gesture_scroll_on_impl_thread_) @@ -921,6 +806,8 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureFlingStart( const WebGestureEvent& gesture_event) { + // Touchpad flings are handled on browser. + DCHECK(!(gesture_event.source_device == blink::kWebGestureDeviceTouchpad)); #ifndef NDEBUG expect_scroll_update_end_ = false; #endif @@ -933,15 +820,6 @@ scroll_status.main_thread_scrolling_reasons = cc::MainThreadScrollingReason::kNotScrollingOnMain; switch (gesture_event.source_device) { - case blink::kWebGestureDeviceTouchpad: - if (gesture_event.data.fling_start.target_viewport) { - scroll_status = input_handler_->RootScrollBegin( - &scroll_state, cc::InputHandler::NON_BUBBLING_GESTURE); - } else { - scroll_status = input_handler_->ScrollBegin( - &scroll_state, cc::InputHandler::NON_BUBBLING_GESTURE); - } - break; case blink::kWebGestureDeviceTouchscreen: case blink::kWebGestureDeviceSyntheticAutoscroll: if (!gesture_scroll_on_impl_thread_) { @@ -952,6 +830,7 @@ scroll_status = input_handler_->FlingScrollBegin(); } break; + case blink::kWebGestureDeviceTouchpad: case blink::kWebGestureDeviceUninitialized: case blink::kWebGestureDeviceCount: NOTREACHED(); @@ -960,12 +839,6 @@ switch (scroll_status.thread) { case cc::InputHandler::SCROLL_ON_IMPL_THREAD: { - if (!touchpad_and_wheel_scroll_latching_enabled_ && - gesture_event.source_device == blink::kWebGestureDeviceTouchpad) { - scroll_state.set_is_ending(true); - input_handler_->ScrollEnd(&scroll_state); - } - const float vx = gesture_event.data.fling_start.velocity_x; const float vy = gesture_event.data.fling_start.velocity_y; UpdateCurrentFlingState(gesture_event, gfx::Vector2dF(vx, vy)); @@ -997,12 +870,6 @@ "InputHandlerProxy::HandleGestureFling::ignored", TRACE_EVENT_SCOPE_THREAD); gesture_scroll_on_impl_thread_ = false; - if (gesture_event.source_device == blink::kWebGestureDeviceTouchpad) { - // We still pass the curve to the main thread if there's nothing - // scrollable, in case something - // registers a handler before the curve is over. - return DID_NOT_HANDLE; - } return DROP_EVENT; } } @@ -1171,7 +1038,7 @@ } } - bool fling_is_active = fling_curve_->Apply( + bool fling_is_active = fling_curve_->AdvanceAndApplyToTarget( monotonic_time_sec - fling_parameters_.start_time, this); if (disallow_vertical_fling_scroll_ && disallow_horizontal_fling_scroll_) @@ -1308,9 +1175,7 @@ bool InputHandlerProxy::CancelCurrentFlingWithoutNotifyingClient() { bool had_fling_animation = !!fling_curve_; if (had_fling_animation && - (fling_parameters_.source_device == blink::kWebGestureDeviceTouchscreen || - (touchpad_and_wheel_scroll_latching_enabled_ && - fling_parameters_.source_device == blink::kWebGestureDeviceTouchpad))) { + fling_parameters_.source_device == blink::kWebGestureDeviceTouchscreen) { cc::ScrollStateData scroll_state_data; scroll_state_data.is_ending = true; cc::ScrollState scroll_state(scroll_state_data); @@ -1330,7 +1195,7 @@ has_fling_animation_started_ = false; gesture_scroll_on_impl_thread_ = false; current_fling_velocity_ = gfx::Vector2dF(); - fling_parameters_ = blink::WebActiveWheelFlingParameters(); + fling_parameters_ = blink::WebActiveFlingParameters(); if (fling_booster_) { if (fling_booster_->fling_cancellation_is_deferred()) { @@ -1363,94 +1228,6 @@ input_handler_->SetNeedsAnimateInput(); } -bool InputHandlerProxy::TouchpadFlingScroll( - const WebFloatSize& increment) { - InputHandlerProxy::EventDisposition disposition; - cc::EventListenerProperties properties = - input_handler_->GetEventListenerProperties( - cc::EventListenerClass::kMouseWheel); - switch (properties) { - case cc::EventListenerProperties::kBlockingAndPassive: - case cc::EventListenerProperties::kBlocking: - disposition = DID_NOT_HANDLE; - break; - case cc::EventListenerProperties::kPassive: - case cc::EventListenerProperties::kNone: { - WebMouseWheelEvent synthetic_wheel(WebInputEvent::kMouseWheel, - fling_parameters_.modifiers, - InSecondsF(base::TimeTicks::Now())); - synthetic_wheel.delta_x = increment.width; - synthetic_wheel.delta_y = increment.height; - synthetic_wheel.has_precise_scrolling_deltas = true; - synthetic_wheel.phase = WebMouseWheelEvent::kPhaseChanged; - synthetic_wheel.SetPositionInWidget(fling_parameters_.point.x, - fling_parameters_.point.y); - synthetic_wheel.SetPositionInScreen(fling_parameters_.global_point.x, - fling_parameters_.global_point.y); - - disposition = FlingScrollByMouseWheel(synthetic_wheel, properties); - - // Send the event over to the main thread. - if (disposition == DID_HANDLE_NON_BLOCKING) { - client_->DispatchNonBlockingEventToMainThread( - ui::WebInputEventTraits::Clone(synthetic_wheel), ui::LatencyInfo()); - } - break; - } - default: - NOTREACHED(); - return false; - } - - switch (disposition) { - case DID_HANDLE: - case DID_HANDLE_NON_BLOCKING: - return true; - case DROP_EVENT: - break; - case DID_NOT_HANDLE: { - if (touchpad_and_wheel_scroll_latching_enabled_) { - // Send a GSB to the main thread before transfering the curve. This - // may cause scrolling a different target which will be a non-issue - // once fling is handled on browser side. https://crbug.com/249063 - WebGestureEvent synthetic_begin(WebInputEvent::kGestureScrollBegin, - fling_parameters_.modifiers, - InSecondsF(base::TimeTicks::Now())); - synthetic_begin.x = fling_parameters_.point.x; - synthetic_begin.y = fling_parameters_.point.y; - synthetic_begin.global_x = fling_parameters_.global_point.x; - synthetic_begin.global_y = fling_parameters_.global_point.y; - synthetic_begin.source_device = blink::kWebGestureDeviceTouchpad; - synthetic_begin.data.scroll_begin.delta_x_hint = - fling_parameters_.delta.x; - synthetic_begin.data.scroll_begin.delta_y_hint = - fling_parameters_.delta.y; - client_->DispatchNonBlockingEventToMainThread( - ui::WebInputEventTraits::Clone(synthetic_begin), ui::LatencyInfo()); - } - TRACE_EVENT_INSTANT0("input", - "InputHandlerProxy::scrollBy::AbortFling", - TRACE_EVENT_SCOPE_THREAD); - // If we got a DID_NOT_HANDLE, that means we need to deliver wheels on the - // main thread. In this case we need to schedule a commit and transfer the - // fling curve over to the main thread and run the rest of the wheels from - // there. This can happen when flinging a page that contains a scrollable - // subarea that we can't scroll on the thread if the fling starts outside - // the subarea but then is flung "under" the pointer. - client_->TransferActiveWheelFlingAnimation(fling_parameters_); - fling_may_be_active_on_main_thread_ = true; - CancelCurrentFlingWithoutNotifyingClient(); - break; - } - case DID_NOT_HANDLE_NON_BLOCKING_DUE_TO_FLING: - case DID_HANDLE_SHOULD_BUBBLE: - NOTREACHED(); - return false; - } - - return false; -} - bool InputHandlerProxy::ScrollBy(const WebFloatSize& increment, const WebFloatSize& velocity) { WebFloatSize clipped_increment; @@ -1484,9 +1261,6 @@ bool did_scroll = false; switch (fling_parameters_.source_device) { - case blink::kWebGestureDeviceTouchpad: - did_scroll = TouchpadFlingScroll(clipped_increment); - break; case blink::kWebGestureDeviceTouchscreen: case blink::kWebGestureDeviceSyntheticAutoscroll: { clipped_increment = ToClientScrollIncrement(clipped_increment); @@ -1502,6 +1276,7 @@ HandleOverscroll(fling_parameters_.point, scroll_result, false); did_scroll = scroll_result.did_scroll; } break; + case blink::kWebGestureDeviceTouchpad: case blink::kWebGestureDeviceUninitialized: case blink::kWebGestureDeviceCount: NOTREACHED(); @@ -1547,6 +1322,10 @@ const WebGestureEvent& fling_start_event, const gfx::Vector2dF& velocity) { DCHECK_EQ(WebInputEvent::kGestureFlingStart, fling_start_event.GetType()); + // When wheel scroll latching is enabled touchpad flings are handled on + // browser. + DCHECK(fling_start_event.source_device != blink::kWebGestureDeviceTouchpad || + !touchpad_and_wheel_scroll_latching_enabled_); current_fling_velocity_ = velocity; fling_curve_ = client_->CreateFlingAnimationCurve( fling_start_event.source_device,
diff --git a/ui/events/blink/input_handler_proxy.h b/ui/events/blink/input_handler_proxy.h index 23179ff..b811d90 100644 --- a/ui/events/blink/input_handler_proxy.h +++ b/ui/events/blink/input_handler_proxy.h
@@ -13,7 +13,7 @@ #include "third_party/WebKit/public/platform/WebGestureCurve.h" #include "third_party/WebKit/public/platform/WebGestureCurveTarget.h" #include "third_party/WebKit/public/platform/WebGestureEvent.h" -#include "third_party/WebKit/public/web/WebActiveWheelFlingParameters.h" +#include "third_party/WebKit/public/web/WebActiveFlingParameters.h" #include "ui/events/blink/blink_features.h" #include "ui/events/blink/input_scroll_elasticity_controller.h" #include "ui/events/blink/synchronous_input_handler_proxy.h" @@ -135,9 +135,6 @@ // Helper functions for handling more complicated input events. EventDisposition HandleMouseWheel( const blink::WebMouseWheelEvent& event); - EventDisposition FlingScrollByMouseWheel( - const blink::WebMouseWheelEvent& event, - cc::EventListenerProperties listener_properties); EventDisposition HandleGestureScrollBegin( const blink::WebGestureEvent& event); EventDisposition HandleGestureScrollUpdate( @@ -150,9 +147,6 @@ EventDisposition HandleTouchMove(const blink::WebTouchEvent& event); EventDisposition HandleTouchEnd(const blink::WebTouchEvent& event); - // Returns true if we scrolled by the increment. - bool TouchpadFlingScroll(const blink::WebFloatSize& increment); - // Returns true if we actually had an active fling to cancel, also notifying // the client that the fling has ended. Note that if a boosted fling is active // and suppressing an active scroll sequence, a synthetic GestureScrollBegin @@ -198,7 +192,7 @@ std::unique_ptr<blink::WebGestureCurve> fling_curve_; // Parameters for the active fling animation, stored in case we need to // transfer it out later. - blink::WebActiveWheelFlingParameters fling_parameters_; + blink::WebActiveFlingParameters fling_parameters_; InputHandlerProxyClient* client_; cc::InputHandler* input_handler_;
diff --git a/ui/events/blink/input_handler_proxy_client.h b/ui/events/blink/input_handler_proxy_client.h index 4e1d602..9f2fb2f 100644 --- a/ui/events/blink/input_handler_proxy_client.h +++ b/ui/events/blink/input_handler_proxy_client.h
@@ -9,7 +9,6 @@ namespace blink { class WebGestureCurve; -struct WebActiveWheelFlingParameters; struct WebFloatPoint; struct WebSize; } @@ -22,11 +21,6 @@ // Called just before the InputHandlerProxy shuts down. virtual void WillShutdown() = 0; - // Transfers an active wheel fling animation initiated by a previously - // handled input event out to the client. - virtual void TransferActiveWheelFlingAnimation( - const blink::WebActiveWheelFlingParameters& params) = 0; - // Dispatch a non blocking event to the main thread. This is used when a // gesture fling from a touchpad is processed and the target only has // passive event listeners. If the target has blocking event listeners
diff --git a/ui/events/blink/input_handler_proxy_unittest.cc b/ui/events/blink/input_handler_proxy_unittest.cc index e322176..6e5137e 100644 --- a/ui/events/blink/input_handler_proxy_unittest.cc +++ b/ui/events/blink/input_handler_proxy_unittest.cc
@@ -41,7 +41,6 @@ #include "ui/gfx/geometry/size_f.h" #include "ui/latency/latency_info.h" -using blink::WebActiveWheelFlingParameters; using blink::WebFloatPoint; using blink::WebFloatSize; using blink::WebGestureDevice; @@ -83,17 +82,6 @@ return (time - base::TimeTicks()).InSecondsF(); } -bool WheelEventsMatch(const WebInputEvent& lhs, const WebInputEvent& rhs) { - if (lhs.size() == rhs.size() && lhs.GetType() == rhs.GetType() && - lhs.GetType() == WebInputEvent::kMouseWheel) { - WebMouseWheelEvent rhs_timestamped = - static_cast<const WebMouseWheelEvent&>(rhs); - rhs_timestamped.SetTimeStampSeconds(lhs.TimeStampSeconds()); - return memcmp(&rhs_timestamped, &lhs, rhs.size()) == 0; - } - return false; -} - MATCHER_P(WheelEventsMatch, expected, "") { return WheelEventsMatch(arg, expected); } @@ -106,6 +94,8 @@ int modifiers) { WebGestureEvent fling(WebInputEvent::kGestureFlingStart, modifiers, (timestamp - base::TimeTicks()).InSecondsF()); + // Touchpad fling is handled on broswer. + DCHECK(source_device != blink::kWebGestureDeviceTouchpad); fling.source_device = source_device; fling.data.fling_start.velocity_x = velocity.x; fling.data.fling_start.velocity_y = velocity.y; @@ -141,6 +131,8 @@ if (type == WebInputEvent::kGestureScrollUpdate) { gesture.data.scroll_update.delta_y = delta_y_or_scale; } else if (type == WebInputEvent::kGestureFlingStart) { + // Touchpad fling is handled on broswer. + DCHECK(source_device != blink::kWebGestureDeviceTouchpad); gesture.data.fling_start.velocity_y = delta_y_or_scale; } else if (type == WebInputEvent::kGesturePinchUpdate) { gesture.data.pinch_update.scale = delta_y_or_scale; @@ -260,22 +252,22 @@ ~FakeWebGestureCurve() override {} - // Returns false if curve has finished and can no longer be applied. - bool Apply(double time, blink::WebGestureCurveTarget* target) override { - blink::WebFloatSize displacement(velocity_.width * time, - velocity_.height * time); - blink::WebFloatSize increment( - displacement.width - cumulative_scroll_.width, - displacement.height - cumulative_scroll_.height); + bool Advance(double time, + gfx::Vector2dF& out_current_velocity, + gfx::Vector2dF& out_delta_to_scroll) override { + out_current_velocity = velocity_; + gfx::Vector2dF displacement = velocity_; + displacement.Scale(time); + out_delta_to_scroll = displacement - cumulative_scroll_; cumulative_scroll_ = displacement; - // scrollBy() could delete this curve if the animation is over, so don't - // touch any member variables after making that call. - return target->ScrollBy(increment, velocity_); + + // The curve is always active. + return true; } private: - blink::WebFloatSize velocity_; - blink::WebFloatSize cumulative_scroll_; + gfx::Vector2dF velocity_; + gfx::Vector2dF cumulative_scroll_; DISALLOW_COPY_AND_ASSIGN(FakeWebGestureCurve); }; @@ -288,9 +280,6 @@ void WillShutdown() override {} - MOCK_METHOD1(TransferActiveWheelFlingAnimation, - void(const WebActiveWheelFlingParameters&)); - MOCK_METHOD1(DispatchNonBlockingEventToMainThread_, void(const WebInputEvent&)); @@ -502,14 +491,9 @@ } protected: - void GestureFlingAnimatesTouchpad(); - void DidReceiveInputEvent_ForFling(); void GestureScrollStarted(); - void GestureFlingPassiveListener(); - void GestureFlingStartedTouchpad(); - void GestureFlingStopsAtContentEdge(); - void GestureFlingTransferResetsTouchpad(); void ScrollHandlingSwitchedToMainThread(); + void GestureScrollIgnored(); const bool synchronous_root_scroll_; const bool install_synchronous_handler_; @@ -767,7 +751,7 @@ VERIFY_AND_RESET_MOCKS(); } -TEST_P(InputHandlerProxyTest, GestureScrollIgnored) { +void InputHandlerProxyTest::GestureScrollIgnored() { // We shouldn't handle the GestureScrollBegin. // Instead, we should get a DROP_EVENT result, indicating // that we could determine that there's nothing that could scroll or otherwise @@ -793,12 +777,12 @@ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); VERIFY_AND_RESET_MOCKS(); - - expected_disposition_ = InputHandlerProxy::DROP_EVENT; - gesture_.SetType(WebInputEvent::kGestureFlingStart); - EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - - VERIFY_AND_RESET_MOCKS(); +} +TEST_P(InputHandlerProxyTest, GestureScrollIgnored) { + GestureScrollIgnored(); +} +TEST_P(InputHandlerProxyWithoutWheelScrollLatchingTest, GestureScrollIgnored) { + GestureScrollIgnored(); } TEST_P(InputHandlerProxyTest, GestureScrollByPage) { @@ -1034,54 +1018,6 @@ VERIFY_AND_RESET_MOCKS(); } -void InputHandlerProxyTest::GestureFlingStartedTouchpad() { - // We shouldn't send any events to the widget for this gesture. - expected_disposition_ = InputHandlerProxy::DID_HANDLE; - VERIFY_AND_RESET_MOCKS(); - - EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_)) - .WillOnce(testing::Return(kImplThreadScrollState)); - - // HandleGestureScrollBegin will set gesture_scroll_on_impl_thread_. - gesture_.SetType(WebInputEvent::kGestureScrollBegin); - EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); - - VERIFY_AND_RESET_MOCKS(); - - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .WillOnce(testing::Return(kImplThreadScrollState)); - if (!touchpad_and_wheel_scroll_latching_enabled_) - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)); - EXPECT_SET_NEEDS_ANIMATE_INPUT(1); - - gesture_.SetType(WebInputEvent::kGestureFlingStart); - gesture_.data.fling_start.velocity_x = 10; - gesture_.source_device = blink::kWebGestureDeviceTouchpad; - EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - - VERIFY_AND_RESET_MOCKS(); - - if (touchpad_and_wheel_scroll_latching_enabled_) { - // The fling cancellation shouldn't get deferred because velocityX is less - // than minimum. - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)).Times(1); - } - // Verify that a GestureFlingCancel during an animation cancels it. - gesture_.SetType(WebInputEvent::kGestureFlingCancel); - gesture_.source_device = blink::kWebGestureDeviceTouchpad; - EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - - VERIFY_AND_RESET_MOCKS(); -} -TEST_P(InputHandlerProxyTest, GestureFlingStartedTouchpad) { - GestureFlingStartedTouchpad(); -} -TEST_P(InputHandlerProxyWithoutWheelScrollLatchingTest, - GestureFlingStartedTouchpad) { - GestureFlingStartedTouchpad(); -} - void InputHandlerProxyTest::ScrollHandlingSwitchedToMainThread() { // We shouldn't send any events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_HANDLE; @@ -1137,658 +1073,6 @@ ScrollHandlingSwitchedToMainThread(); } -TEST_P(InputHandlerProxyTest, GestureFlingTouchpadScrollLatchingEnabled) { - // Reset the input_handler_ with wheel scroll latching enabled. - input_handler_.reset( - new TestInputHandlerProxy(&mock_input_handler_, &mock_client_, true)); - if (install_synchronous_handler_) { - EXPECT_CALL(mock_input_handler_, RequestUpdateForSynchronousInputHandler()) - .Times(1); - input_handler_->SetOnlySynchronouslyAnimateRootFlings( - &mock_synchronous_input_handler_); - } - - // We shouldn't send any events to the widget for this gesture. - expected_disposition_ = InputHandlerProxy::DID_HANDLE; - VERIFY_AND_RESET_MOCKS(); - - EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_)) - .WillOnce(testing::Return(kImplThreadScrollState)); - - // HandleGestureScrollBegin will set gesture_scroll_on_impl_thread_. - gesture_.SetType(WebInputEvent::kGestureScrollBegin); - EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); - - VERIFY_AND_RESET_MOCKS(); - - // On the fling start, we should schedule an animation but not actually start - // scrolling. - gesture_.SetType(WebInputEvent::kGestureFlingStart); - WebFloatPoint fling_delta = WebFloatPoint(1000, 0); - WebPoint fling_point = WebPoint(7, 13); - WebPoint fling_global_point = WebPoint(17, 23); - // Note that for trackpad, wheel events with the Control modifier are - // special (reserved for zoom), so don't set that here. - int modifiers = WebInputEvent::kShiftKey | WebInputEvent::kAltKey; - gesture_ = CreateFling(blink::kWebGestureDeviceTouchpad, fling_delta, - fling_point, fling_global_point, modifiers); - EXPECT_SET_NEEDS_ANIMATE_INPUT(1); - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .WillOnce(testing::Return(kImplThreadScrollState)); - - // When scroll latching is enabled, ScrollEnd shouldn't get called while - // handling GestureFlingStart. - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)).Times(0); - EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - - VERIFY_AND_RESET_MOCKS(); - - // The first animate call won't start scrolling. - EXPECT_SET_NEEDS_ANIMATE_INPUT(1); - base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); - Animate(time); - - VERIFY_AND_RESET_MOCKS(); - - // The second call should start scrolling in the -X direction. - EXPECT_SET_NEEDS_ANIMATE_INPUT(1); - EXPECT_CALL(mock_input_handler_, - GetEventListenerProperties(cc::EventListenerClass::kMouseWheel)) - .WillOnce(testing::Return(cc::EventListenerProperties::kNone)); - - // When scroll latching is enabled, ScrollBegin shouldn't get called for - // every tick. - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .Times(0); - EXPECT_CALL( - mock_input_handler_, - ScrollBy(testing::Property(&cc::ScrollState::delta_x, testing::Lt(0)))) - .WillOnce(testing::Return(scroll_result_did_scroll_)); - - // When scroll latching is enabled, ScrollEnd shouldn't get called for every - // tick. - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)).Times(0); - time += base::TimeDelta::FromMilliseconds(100); - Animate(time); - - VERIFY_AND_RESET_MOCKS(); - - // The last call should stop scrolling. - EXPECT_CALL(mock_input_handler_, - GetEventListenerProperties(cc::EventListenerClass::kMouseWheel)) - .WillOnce(testing::Return(cc::EventListenerProperties::kNone)); - - // When scroll latching is enabled, ScrollBegin shouldn't get called for - // every tick. - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .Times(0); - EXPECT_CALL( - mock_input_handler_, - ScrollBy(testing::Property(&cc::ScrollState::delta_x, testing::Lt(0)))) - .WillOnce(testing::Return(scroll_result_did_not_scroll_)); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillOnce(testing::Return(false)); - - // When scroll latching is enabled, ScrollEnd gets called when the last - // ScrollBy did not scroll. - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)); - time += base::TimeDelta::FromMilliseconds(100); - Animate(time); - - VERIFY_AND_RESET_MOCKS(); - - // Fling has ended, the last Animate won't cause any more wheel ticks. - EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_)).Times(0); - time += base::TimeDelta::FromMilliseconds(100); - Animate(time); - - VERIFY_AND_RESET_MOCKS(); -} - -TEST_P(InputHandlerProxyTest, GestureFlingOnMainThreadTouchpad) { - // We should send all events to the widget for this gesture. - expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; - VERIFY_AND_RESET_MOCKS(); - - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .WillOnce(testing::Return(kMainThreadScrollState)); - - gesture_.SetType(WebInputEvent::kGestureFlingStart); - gesture_.source_device = blink::kWebGestureDeviceTouchpad; - EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - - // Since we returned ScrollStatusOnMainThread from scrollBegin, ensure the - // input handler knows it's scrolling off the impl thread - ASSERT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); - - VERIFY_AND_RESET_MOCKS(); - - // Even if we didn't start a fling ourselves, we still need to send the cancel - // event to the widget. - gesture_.SetType(WebInputEvent::kGestureFlingCancel); - gesture_.source_device = blink::kWebGestureDeviceTouchpad; - EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); -} - -TEST_P(InputHandlerProxyTest, GestureFlingIgnoredTouchpad) { - expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; - VERIFY_AND_RESET_MOCKS(); - - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .WillOnce(testing::Return(kScrollIgnoredScrollState)); - - gesture_.SetType(WebInputEvent::kGestureFlingStart); - gesture_.source_device = blink::kWebGestureDeviceTouchpad; - EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - - expected_disposition_ = InputHandlerProxy::DROP_EVENT; - VERIFY_AND_RESET_MOCKS(); - - // Since the previous fling was ignored, we should also be dropping the next - // fling_cancel. - gesture_.SetType(WebInputEvent::kGestureFlingCancel); - gesture_.source_device = blink::kWebGestureDeviceTouchpad; - EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); -} - -void InputHandlerProxyTest::GestureFlingAnimatesTouchpad() { - // We shouldn't send any events to the widget for this gesture. - expected_disposition_ = InputHandlerProxy::DID_HANDLE; - VERIFY_AND_RESET_MOCKS(); - - EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_)) - .WillOnce(testing::Return(kImplThreadScrollState)); - - // HandleGestureScrollBegin will set gesture_scroll_on_impl_thread_. - gesture_.SetType(WebInputEvent::kGestureScrollBegin); - EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); - - VERIFY_AND_RESET_MOCKS(); - - // On the fling start, we should schedule an animation but not actually start - // scrolling. - gesture_.SetType(WebInputEvent::kGestureFlingStart); - WebFloatPoint fling_delta = WebFloatPoint(1000, 0); - WebPoint fling_point = WebPoint(7, 13); - WebPoint fling_global_point = WebPoint(17, 23); - // Note that for trackpad, wheel events with the Control modifier are - // special (reserved for zoom), so don't set that here. - int modifiers = WebInputEvent::kShiftKey | WebInputEvent::kAltKey; - gesture_ = CreateFling(blink::kWebGestureDeviceTouchpad, fling_delta, - fling_point, fling_global_point, modifiers); - EXPECT_SET_NEEDS_ANIMATE_INPUT(1); - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .WillOnce(testing::Return(kImplThreadScrollState)); - if (!touchpad_and_wheel_scroll_latching_enabled_) - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)); - EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - - VERIFY_AND_RESET_MOCKS(); - - // The first animate call should let us pick up an animation start time, but - // we shouldn't actually move anywhere just yet. The first frame after the - // fling start will typically include the last scroll from the gesture that - // lead to the scroll (either wheel or gesture scroll), so there should be no - // visible hitch. - EXPECT_SET_NEEDS_ANIMATE_INPUT(1); - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .Times(0); - base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); - Animate(time); - - VERIFY_AND_RESET_MOCKS(); - - // The second call should start scrolling in the -X direction. - EXPECT_SET_NEEDS_ANIMATE_INPUT(1); - EXPECT_CALL(mock_input_handler_, - GetEventListenerProperties(cc::EventListenerClass::kMouseWheel)) - .WillOnce(testing::Return(cc::EventListenerProperties::kNone)); - if (!touchpad_and_wheel_scroll_latching_enabled_) { - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .WillOnce(testing::Return(kImplThreadScrollState)); - } - EXPECT_CALL( - mock_input_handler_, - ScrollBy(testing::Property(&cc::ScrollState::delta_x, testing::Lt(0)))) - .WillOnce(testing::Return(scroll_result_did_scroll_)); - if (!touchpad_and_wheel_scroll_latching_enabled_) - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)); - time += base::TimeDelta::FromMilliseconds(100); - Animate(time); - - VERIFY_AND_RESET_MOCKS(); - - // Let's say on the third call we hit a non-scrollable region. We should abort - // the fling and not scroll. - // We also should pass the current fling parameters out to the client so the - // rest of the fling can be - // transferred to the main thread. - EXPECT_CALL(mock_input_handler_, - GetEventListenerProperties(cc::EventListenerClass::kMouseWheel)) - .WillOnce(testing::Return(cc::EventListenerProperties::kNone)); - if (!touchpad_and_wheel_scroll_latching_enabled_) { - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .WillOnce(testing::Return(kMainThreadScrollState)); - EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_)).Times(0); - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)).Times(0); - } else { - EXPECT_CALL( - mock_input_handler_, - ScrollBy(testing::Property(&cc::ScrollState::delta_x, testing::Lt(0)))) - .WillOnce(testing::Return(scroll_result_did_not_scroll_)); - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillOnce(testing::Return(true)); - // A GSB is sent to the main thread before transfering the fling. - EXPECT_CALL(mock_client_, DispatchNonBlockingEventToMainThread_(testing::_)) - .Times(1); - } - // Expected wheel fling animation parameters: - // *) fling_delta and fling_point should match the original GestureFlingStart - // event - // *) startTime should be 10 to match the time parameter of the first - // Animate() call after the GestureFlingStart - // *) cumulativeScroll depends on the curve, but since we've animated in the - // -X direction the X value should be < 0 - EXPECT_CALL( - mock_client_, - TransferActiveWheelFlingAnimation(testing::AllOf( - testing::Field(&WebActiveWheelFlingParameters::delta, - testing::Eq(fling_delta)), - testing::Field(&WebActiveWheelFlingParameters::point, - testing::Eq(fling_point)), - testing::Field(&WebActiveWheelFlingParameters::global_point, - testing::Eq(fling_global_point)), - testing::Field(&WebActiveWheelFlingParameters::modifiers, - testing::Eq(modifiers)), - testing::Field(&WebActiveWheelFlingParameters::start_time, - testing::Eq(10)), - testing::Field(&WebActiveWheelFlingParameters::cumulative_scroll, - testing::Field(&WebSize::width, testing::Gt(0)))))); - time += base::TimeDelta::FromMilliseconds(100); - Animate(time); - - VERIFY_AND_RESET_MOCKS(); - - // Since we've aborted the fling, the next animation should be a no-op and - // should not result in another - // frame being requested. - EXPECT_SET_NEEDS_ANIMATE_INPUT(0); - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .Times(0); - time += base::TimeDelta::FromMilliseconds(100); - Animate(time); - - // Since we've transferred the fling to the main thread, we need to pass the - // next GestureFlingCancel to the main - // thread as well. - expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; - gesture_.SetType(WebInputEvent::kGestureFlingCancel); - EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - - VERIFY_AND_RESET_MOCKS(); -} -TEST_P(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) { - GestureFlingAnimatesTouchpad(); -} -TEST_P(InputHandlerProxyWithoutWheelScrollLatchingTest, - GestureFlingAnimatesTouchpad) { - GestureFlingAnimatesTouchpad(); -} - -void InputHandlerProxyTest::GestureFlingPassiveListener() { - // We shouldn't send any events to the widget for this gesture. - expected_disposition_ = InputHandlerProxy::DID_HANDLE; - VERIFY_AND_RESET_MOCKS(); - - EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_)) - .WillOnce(testing::Return(kImplThreadScrollState)); - - // HandleGestureScrollBegin will set gesture_scroll_on_impl_thread_. - gesture_.SetType(WebInputEvent::kGestureScrollBegin); - EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); - - VERIFY_AND_RESET_MOCKS(); - - // On the fling start, we should schedule an animation but not actually start - // scrolling. - gesture_.SetType(WebInputEvent::kGestureFlingStart); - WebFloatPoint fling_delta = WebFloatPoint(1000, 0); - WebPoint fling_point = WebPoint(7, 13); - WebPoint fling_global_point = WebPoint(17, 23); - // Note that for trackpad, wheel events with the Control modifier are - // special (reserved for zoom), so don't set that here. - int modifiers = WebInputEvent::kShiftKey | WebInputEvent::kAltKey; - gesture_ = CreateFling(blink::kWebGestureDeviceTouchpad, fling_delta, - fling_point, fling_global_point, modifiers); - EXPECT_SET_NEEDS_ANIMATE_INPUT(1); - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .WillOnce(testing::Return(kImplThreadScrollState)); - if (!touchpad_and_wheel_scroll_latching_enabled_) - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)); - EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - - VERIFY_AND_RESET_MOCKS(); - - // The first animate call should let us pick up an animation start time, but - // we shouldn't actually move anywhere just yet. The first frame after the - // fling start will typically include the last scroll from the gesture that - // lead to the scroll (either wheel or gesture scroll), so there should be no - // visible hitch. - EXPECT_SET_NEEDS_ANIMATE_INPUT(1); - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .Times(0); - base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); - Animate(time); - - VERIFY_AND_RESET_MOCKS(); - - // The second call should punt activate the fling and call the method - // dispatching the events for the passive event listeners. - EXPECT_SET_NEEDS_ANIMATE_INPUT(1); - EXPECT_CALL(mock_input_handler_, - GetEventListenerProperties(cc::EventListenerClass::kMouseWheel)) - .WillOnce(testing::Return(cc::EventListenerProperties::kPassive)); - if (!touchpad_and_wheel_scroll_latching_enabled_) { - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .WillOnce(testing::Return(kImplThreadScrollState)); - } - EXPECT_CALL( - mock_input_handler_, - ScrollBy(testing::Property(&cc::ScrollState::delta_x, testing::Lt(0)))) - .WillOnce(testing::Return(scroll_result_did_scroll_)); - WebMouseWheelEvent expected_wheel(WebInputEvent::kMouseWheel, modifiers, - WebInputEvent::kTimeStampForTesting); - expected_wheel.SetPositionInWidget(fling_point.x, fling_point.y); - expected_wheel.SetPositionInScreen(fling_global_point.x, - fling_global_point.y); - expected_wheel.delta_x = fling_delta.x / 10; - expected_wheel.has_precise_scrolling_deltas = true; - expected_wheel.phase = WebMouseWheelEvent::kPhaseChanged; - - EXPECT_CALL(mock_client_, DispatchNonBlockingEventToMainThread_( - WheelEventsMatch(expected_wheel))) - .Times(1); - if (!touchpad_and_wheel_scroll_latching_enabled_) - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)).Times(1); - - time += base::TimeDelta::FromMilliseconds(100); - Animate(time); - - VERIFY_AND_RESET_MOCKS(); - - // Ensure we can cancel the gesture. - expected_disposition_ = InputHandlerProxy::DID_HANDLE; - gesture_.SetType(WebInputEvent::kGestureFlingCancel); - EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - if (touchpad_and_wheel_scroll_latching_enabled_) { - // The fling cancellation should be deferred. - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)).Times(0); - } - - VERIFY_AND_RESET_MOCKS(); -} -TEST_P(InputHandlerProxyTest, GestureFlingPassiveListener) { - GestureFlingPassiveListener(); -} -TEST_P(InputHandlerProxyWithoutWheelScrollLatchingTest, - GestureFlingPassiveListener) { - GestureFlingPassiveListener(); -} - -void InputHandlerProxyTest::GestureFlingTransferResetsTouchpad() { - // We shouldn't send any events to the widget for this gesture. - expected_disposition_ = InputHandlerProxy::DID_HANDLE; - VERIFY_AND_RESET_MOCKS(); - - EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_)) - .WillOnce(testing::Return(kImplThreadScrollState)); - - // HandleGestureScrollBegin will set gesture_scroll_on_impl_thread_. - gesture_.SetType(WebInputEvent::kGestureScrollBegin); - EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); - - VERIFY_AND_RESET_MOCKS(); - - // Start a gesture fling in the -X direction with zero Y movement. - WebFloatPoint fling_delta = WebFloatPoint(1000, 0); - WebPoint fling_point = WebPoint(7, 13); - WebPoint fling_global_point = WebPoint(17, 23); - // Note that for trackpad, wheel events with the Control modifier are - // special (reserved for zoom), so don't set that here. - int modifiers = WebInputEvent::kShiftKey | WebInputEvent::kAltKey; - gesture_ = CreateFling(blink::kWebGestureDeviceTouchpad, fling_delta, - fling_point, fling_global_point, modifiers); - EXPECT_SET_NEEDS_ANIMATE_INPUT(1); - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .WillOnce(testing::Return(kImplThreadScrollState)); - if (!touchpad_and_wheel_scroll_latching_enabled_) - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)); - EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - VERIFY_AND_RESET_MOCKS(); - - // Start the fling animation at time 10. This shouldn't actually scroll, just - // establish a start time. - EXPECT_SET_NEEDS_ANIMATE_INPUT(1); - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .Times(0); - base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); - Animate(time); - - VERIFY_AND_RESET_MOCKS(); - - // The second call should start scrolling in the -X direction. - EXPECT_SET_NEEDS_ANIMATE_INPUT(1); - EXPECT_CALL(mock_input_handler_, - GetEventListenerProperties(cc::EventListenerClass::kMouseWheel)) - .WillOnce(testing::Return(cc::EventListenerProperties::kNone)); - if (!touchpad_and_wheel_scroll_latching_enabled_) { - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .WillOnce(testing::Return(kImplThreadScrollState)); - } - EXPECT_CALL( - mock_input_handler_, - ScrollBy(testing::Property(&cc::ScrollState::delta_x, testing::Lt(0)))) - .WillOnce(testing::Return(scroll_result_did_scroll_)); - if (!touchpad_and_wheel_scroll_latching_enabled_) - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)); - time += base::TimeDelta::FromMilliseconds(100); - Animate(time); - - VERIFY_AND_RESET_MOCKS(); - - // Let's say on the third call we hit a non-scrollable region. We should abort - // the fling and not scroll. - // We also should pass the current fling parameters out to the client so the - // rest of the fling can be - // transferred to the main thread. - EXPECT_CALL(mock_input_handler_, - GetEventListenerProperties(cc::EventListenerClass::kMouseWheel)) - .WillOnce(testing::Return(cc::EventListenerProperties::kNone)); - if (!touchpad_and_wheel_scroll_latching_enabled_) { - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .WillOnce(testing::Return(kMainThreadScrollState)); - EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_)).Times(0); - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)).Times(0); - } else { - EXPECT_CALL( - mock_input_handler_, - ScrollBy(testing::Property(&cc::ScrollState::delta_x, testing::Lt(0)))) - .WillOnce(testing::Return(scroll_result_did_not_scroll_)); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillOnce(testing::Return(true)); - // A GSB is sent to the main thread before transfering the fling. - EXPECT_CALL(mock_client_, DispatchNonBlockingEventToMainThread_(testing::_)) - .Times(1); - } - - // Expected wheel fling animation parameters: - // *) fling_delta and fling_point should match the original GestureFlingStart - // event - // *) startTime should be 10 to match the time parameter of the first - // Animate() call after the GestureFlingStart - // *) cumulativeScroll depends on the curve, but since we've animated in the - // -X direction the X value should be < 0 - EXPECT_CALL( - mock_client_, - TransferActiveWheelFlingAnimation(testing::AllOf( - testing::Field(&WebActiveWheelFlingParameters::delta, - testing::Eq(fling_delta)), - testing::Field(&WebActiveWheelFlingParameters::point, - testing::Eq(fling_point)), - testing::Field(&WebActiveWheelFlingParameters::global_point, - testing::Eq(fling_global_point)), - testing::Field(&WebActiveWheelFlingParameters::modifiers, - testing::Eq(modifiers)), - testing::Field(&WebActiveWheelFlingParameters::start_time, - testing::Eq(10)), - testing::Field(&WebActiveWheelFlingParameters::cumulative_scroll, - testing::Field(&WebSize::width, testing::Gt(0)))))); - if (touchpad_and_wheel_scroll_latching_enabled_) - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)); - - time += base::TimeDelta::FromMilliseconds(100); - Animate(time); - - VERIFY_AND_RESET_MOCKS(); - - // Since we've aborted the fling, the next animation should be a no-op and - // should not result in another - // frame being requested. - EXPECT_SET_NEEDS_ANIMATE_INPUT(0); - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .Times(0); - time += base::TimeDelta::FromMilliseconds(100); - Animate(time); - - VERIFY_AND_RESET_MOCKS(); - - // Since we've transferred the fling to the main thread, we need to pass the - // next GestureFlingCancel to the main - // thread as well. - expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; - gesture_.SetType(WebInputEvent::kGestureFlingCancel); - EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - - VERIFY_AND_RESET_MOCKS(); - input_handler_->MainThreadHasStoppedFlinging(); - - EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_)) - .WillOnce(testing::Return(kImplThreadScrollState)); - - // HandleGestureScrollBegin will set gesture_scroll_on_impl_thread_. - expected_disposition_ = InputHandlerProxy::DID_HANDLE; - gesture_.SetType(WebInputEvent::kGestureScrollBegin); - EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); - - VERIFY_AND_RESET_MOCKS(); - - // Start a second gesture fling, this time in the +Y direction with no X. - fling_delta = WebFloatPoint(0, -1000); - fling_point = WebPoint(95, 87); - fling_global_point = WebPoint(32, 71); - modifiers = WebInputEvent::kAltKey; - gesture_ = CreateFling(blink::kWebGestureDeviceTouchpad, fling_delta, - fling_point, fling_global_point, modifiers); - EXPECT_SET_NEEDS_ANIMATE_INPUT(1); - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .WillOnce(testing::Return(kImplThreadScrollState)); - if (!touchpad_and_wheel_scroll_latching_enabled_) - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)); - expected_disposition_ = InputHandlerProxy::DID_HANDLE; - EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - - VERIFY_AND_RESET_MOCKS(); - - // Start the second fling animation at time 30. - EXPECT_SET_NEEDS_ANIMATE_INPUT(1); - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .Times(0); - time = base::TimeTicks() + base::TimeDelta::FromSeconds(30); - Animate(time); - - VERIFY_AND_RESET_MOCKS(); - - // Tick the second fling once normally. - EXPECT_SET_NEEDS_ANIMATE_INPUT(1); - EXPECT_CALL(mock_input_handler_, - GetEventListenerProperties(cc::EventListenerClass::kMouseWheel)) - .WillOnce(testing::Return(cc::EventListenerProperties::kNone)); - if (!touchpad_and_wheel_scroll_latching_enabled_) { - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .WillOnce(testing::Return(kImplThreadScrollState)); - } - EXPECT_CALL( - mock_input_handler_, - ScrollBy(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)))) - .WillOnce(testing::Return(scroll_result_did_scroll_)); - if (!touchpad_and_wheel_scroll_latching_enabled_) - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)); - time += base::TimeDelta::FromMilliseconds(100); - Animate(time); - - VERIFY_AND_RESET_MOCKS(); - - // Then abort the second fling. - EXPECT_CALL(mock_input_handler_, - GetEventListenerProperties(cc::EventListenerClass::kMouseWheel)) - .WillOnce(testing::Return(cc::EventListenerProperties::kNone)); - if (!touchpad_and_wheel_scroll_latching_enabled_) { - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .WillOnce(testing::Return(kMainThreadScrollState)); - EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_)).Times(0); - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)).Times(0); - } else { - EXPECT_CALL( - mock_input_handler_, - ScrollBy(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0)))) - .WillOnce(testing::Return(scroll_result_did_not_scroll_)); - EXPECT_CALL(mock_input_handler_, ScrollingShouldSwitchtoMainThread()) - .WillOnce(testing::Return(true)); - // A GSB is sent to the main thread before transfering the fling. - EXPECT_CALL(mock_client_, DispatchNonBlockingEventToMainThread_(testing::_)) - .Times(1); - } - - // We should get parameters from the second fling, nothing from the first - // fling should "leak". - EXPECT_CALL( - mock_client_, - TransferActiveWheelFlingAnimation(testing::AllOf( - testing::Field(&WebActiveWheelFlingParameters::delta, - testing::Eq(fling_delta)), - testing::Field(&WebActiveWheelFlingParameters::point, - testing::Eq(fling_point)), - testing::Field(&WebActiveWheelFlingParameters::global_point, - testing::Eq(fling_global_point)), - testing::Field(&WebActiveWheelFlingParameters::modifiers, - testing::Eq(modifiers)), - testing::Field(&WebActiveWheelFlingParameters::start_time, - testing::Eq(30)), - testing::Field(&WebActiveWheelFlingParameters::cumulative_scroll, - testing::Field(&WebSize::height, testing::Lt(0)))))); - - if (touchpad_and_wheel_scroll_latching_enabled_) - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)); - - time += base::TimeDelta::FromMilliseconds(100); - Animate(time); - - VERIFY_AND_RESET_MOCKS(); -} -TEST_P(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) { - GestureFlingTransferResetsTouchpad(); -} -TEST_P(InputHandlerProxyWithoutWheelScrollLatchingTest, - GestureFlingTransferResetsTouchpad) { - GestureFlingTransferResetsTouchpad(); -} - TEST_P(InputHandlerProxyTest, GestureFlingStartedTouchscreen) { // We shouldn't send any events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_HANDLE; @@ -2185,7 +1469,8 @@ VERIFY_AND_RESET_MOCKS(); } -void InputHandlerProxyTest::GestureFlingStopsAtContentEdge() { +TEST_P(InputHandlerProxyTest, GestureFlingStopsAtContentEdgeTouchscreen) { + gesture_.source_device = blink::kWebGestureDeviceTouchscreen; // We shouldn't send any events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -2200,16 +1485,15 @@ VERIFY_AND_RESET_MOCKS(); + EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) + .WillOnce(testing::Return(kImplThreadScrollState)); + // On the fling start, we should schedule an animation but not actually start // scrolling. gesture_.SetType(WebInputEvent::kGestureFlingStart); WebFloatPoint fling_delta = WebFloatPoint(100, 100); gesture_.data.fling_start.velocity_x = fling_delta.x; gesture_.data.fling_start.velocity_y = fling_delta.y; - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .WillOnce(testing::Return(kImplThreadScrollState)); - if (!touchpad_and_wheel_scroll_latching_enabled_) - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)); EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); VERIFY_AND_RESET_MOCKS(); @@ -2221,19 +1505,10 @@ VERIFY_AND_RESET_MOCKS(); // The second animate starts scrolling in the positive X and Y directions. - EXPECT_CALL(mock_input_handler_, - GetEventListenerProperties(cc::EventListenerClass::kMouseWheel)) - .WillOnce(testing::Return(cc::EventListenerProperties::kNone)); - if (!touchpad_and_wheel_scroll_latching_enabled_) { - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .WillOnce(testing::Return(kImplThreadScrollState)); - } EXPECT_CALL( mock_input_handler_, ScrollBy(testing::Property(&cc::ScrollState::delta_y, testing::Lt(0)))) .WillOnce(testing::Return(scroll_result_did_scroll_)); - if (!touchpad_and_wheel_scroll_latching_enabled_) - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)); EXPECT_SET_NEEDS_ANIMATE_INPUT(1); time += base::TimeDelta::FromMilliseconds(100); Animate(time); @@ -2246,13 +1521,6 @@ overscroll.did_overscroll_root = true; overscroll.accumulated_root_overscroll = gfx::Vector2dF(0, 100); overscroll.unused_scroll_delta = gfx::Vector2dF(0, 10); - EXPECT_CALL(mock_input_handler_, - GetEventListenerProperties(cc::EventListenerClass::kMouseWheel)) - .WillOnce(testing::Return(cc::EventListenerProperties::kNone)); - if (!touchpad_and_wheel_scroll_latching_enabled_) { - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .WillOnce(testing::Return(kImplThreadScrollState)); - } EXPECT_CALL( mock_input_handler_, ScrollBy(testing::Property(&cc::ScrollState::delta_y, testing::Lt(0)))) @@ -2263,8 +1531,6 @@ overscroll.unused_scroll_delta, testing::Property(&gfx::Vector2dF::y, testing::Lt(0)), testing::_, overscroll.overscroll_behavior)); - if (!touchpad_and_wheel_scroll_latching_enabled_) - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)); EXPECT_SET_NEEDS_ANIMATE_INPUT(1); time += base::TimeDelta::FromMilliseconds(100); Animate(time); @@ -2272,30 +1538,14 @@ // The next call to animate will no longer scroll vertically. EXPECT_SET_NEEDS_ANIMATE_INPUT(1); - EXPECT_CALL(mock_input_handler_, - GetEventListenerProperties(cc::EventListenerClass::kMouseWheel)) - .WillOnce(testing::Return(cc::EventListenerProperties::kNone)); - if (!touchpad_and_wheel_scroll_latching_enabled_) { - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) - .WillOnce(testing::Return(kImplThreadScrollState)); - } EXPECT_CALL( mock_input_handler_, ScrollBy(testing::Property(&cc::ScrollState::delta_y, testing::Eq(0)))) .WillOnce(testing::Return(scroll_result_did_scroll_)); - if (!touchpad_and_wheel_scroll_latching_enabled_) - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)); time += base::TimeDelta::FromMilliseconds(100); Animate(time); VERIFY_AND_RESET_MOCKS(); } -TEST_P(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) { - GestureFlingStopsAtContentEdge(); -} -TEST_P(InputHandlerProxyWithoutWheelScrollLatchingTest, - GestureFlingStopsAtContentEdge) { - GestureFlingStopsAtContentEdge(); -} TEST_P(InputHandlerProxyTest, GestureFlingNotCancelledBySmallTimeDelta) { // We shouldn't send any events to the widget for this gesture. @@ -3345,7 +2595,9 @@ VERIFY_AND_RESET_MOCKS(); } -void InputHandlerProxyTest::DidReceiveInputEvent_ForFling() { + +TEST_P(InputHandlerProxyTest, DidReceiveInputEvent_ForFlingTouchscreen) { + gesture_.source_device = blink::kWebGestureDeviceTouchscreen; testing::StrictMock<MockInputHandlerProxyClientWithDidAnimateForInput> mock_client; input_handler_.reset( @@ -3359,15 +2611,22 @@ } mock_input_handler_.set_is_scrolling_root(synchronous_root_scroll_); + // A GSB must be sent before a GFS. + EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) + .WillOnce(testing::Return(kImplThreadScrollState)); + gesture_.SetType(WebInputEvent::kGestureScrollBegin); + gesture_.source_device = blink::kWebGestureDeviceTouchscreen; + EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); + + VERIFY_AND_RESET_MOCKS(); + gesture_.SetType(WebInputEvent::kGestureFlingStart); WebFloatPoint fling_delta = WebFloatPoint(100, 100); gesture_.data.fling_start.velocity_x = fling_delta.x; gesture_.data.fling_start.velocity_y = fling_delta.y; EXPECT_SET_NEEDS_ANIMATE_INPUT(1); - EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) + EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) .WillOnce(testing::Return(kImplThreadScrollState)); - if (!touchpad_and_wheel_scroll_latching_enabled_) - EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_)); EXPECT_EQ(InputHandlerProxy::DID_HANDLE, input_handler_->HandleInputEvent(gesture_)); VERIFY_AND_RESET_MOCKS(); @@ -3379,13 +2638,6 @@ VERIFY_AND_RESET_MOCKS(); } -TEST_P(InputHandlerProxyTest, DidReceiveInputEvent_ForFling) { - DidReceiveInputEvent_ForFling(); -} -TEST_P(InputHandlerProxyWithoutWheelScrollLatchingTest, - DidReceiveInputEvent_ForFling) { - DidReceiveInputEvent_ForFling(); -} TEST(SynchronousInputHandlerProxyTest, StartupShutdown) { testing::StrictMock<MockInputHandler> mock_input_handler;
diff --git a/ui/events/devices/device_data_manager.cc b/ui/events/devices/device_data_manager.cc index 2f8d318..86b8ebd0 100644 --- a/ui/events/devices/device_data_manager.cc +++ b/ui/events/devices/device_data_manager.cc
@@ -253,16 +253,6 @@ observers_.RemoveObserver(observer); } -void DeviceDataManager::SetKeyboardDevicesForTesting( - const std::vector<InputDevice>& devices) { - OnKeyboardDevicesUpdated(devices); -} - -void DeviceDataManager::SetTouchscreenDevicesForTesting( - const std::vector<TouchscreenDevice>& devices) { - OnTouchscreenDevicesUpdated(devices); -} - void DeviceDataManager::SetTouchscreensEnabled(bool enabled) { touch_screens_enabled_ = enabled; }
diff --git a/ui/events/devices/device_data_manager.h b/ui/events/devices/device_data_manager.h index 75029ae..0e2500b 100644 --- a/ui/events/devices/device_data_manager.h +++ b/ui/events/devices/device_data_manager.h
@@ -62,10 +62,6 @@ bool AreTouchscreenTargetDisplaysValid() const override; void AddObserver(InputDeviceEventObserver* observer) override; void RemoveObserver(InputDeviceEventObserver* observer) override; - void SetKeyboardDevicesForTesting( - const std::vector<InputDevice>& devices) override; - void SetTouchscreenDevicesForTesting( - const std::vector<TouchscreenDevice>& devices) override; protected: DeviceDataManager();
diff --git a/ui/events/devices/input_device_manager.h b/ui/events/devices/input_device_manager.h index d42e62f..dcbd316 100644 --- a/ui/events/devices/input_device_manager.h +++ b/ui/events/devices/input_device_manager.h
@@ -42,11 +42,6 @@ virtual void AddObserver(InputDeviceEventObserver* observer) = 0; virtual void RemoveObserver(InputDeviceEventObserver* observer) = 0; - virtual void SetKeyboardDevicesForTesting( - const std::vector<InputDevice>& devices) = 0; - virtual void SetTouchscreenDevicesForTesting( - const std::vector<TouchscreenDevice>& devices) = 0; - protected: // Sets the instance. This should only be set once per thread. static void SetInstance(InputDeviceManager* instance);
diff --git a/ui/events/event.cc b/ui/events/event.cc index 4149f15..99c06557 100644 --- a/ui/events/event.cc +++ b/ui/events/event.cc
@@ -457,8 +457,7 @@ //////////////////////////////////////////////////////////////////////////////// // LocatedEvent -LocatedEvent::~LocatedEvent() { -} +LocatedEvent::~LocatedEvent() = default; LocatedEvent::LocatedEvent(const base::NativeEvent& native_event) : Event(native_event, @@ -476,6 +475,8 @@ location_(location), root_location_(root_location) {} +LocatedEvent::LocatedEvent(const LocatedEvent& copy) = default; + void LocatedEvent::UpdateForRootTransform( const gfx::Transform& reversed_root_transform, const gfx::Transform& reversed_local_transform) { @@ -542,17 +543,7 @@ offset = pointer_offset; } -PointerDetails::PointerDetails(const PointerDetails& other) - : pointer_type(other.pointer_type), - radius_x(other.radius_x), - radius_y(other.radius_y), - force(other.force), - tilt_x(other.tilt_x), - tilt_y(other.tilt_y), - tangential_pressure(other.tangential_pressure), - twist(other.twist), - id(other.id), - offset(other.offset) {} +PointerDetails::PointerDetails(const PointerDetails& other) = default; const PointerId PointerDetails::kUnknownPointerId = -1; @@ -636,6 +627,10 @@ SetType(ET_MOUSE_DRAGGED); } +MouseEvent::MouseEvent(const MouseEvent& other) = default; + +MouseEvent::~MouseEvent() = default; + // static bool MouseEvent::IsRepeatedClickEvent( const MouseEvent& event1, @@ -811,6 +806,8 @@ SetType(ui::ET_MOUSEWHEEL); } +MouseWheelEvent::~MouseWheelEvent() = default; + #if defined(OS_WIN) // This value matches windows WHEEL_DELTA. // static @@ -1449,6 +1446,10 @@ latency()->set_source_event_type(ui::SourceEventType::WHEEL); } +ScrollEvent::ScrollEvent(const ScrollEvent& other) = default; + +ScrollEvent::~ScrollEvent() = default; + void ScrollEvent::Scale(const float factor) { x_offset_ *= factor; y_offset_ *= factor; @@ -1475,7 +1476,8 @@ latency()->set_source_event_type(ui::SourceEventType::TOUCH); } -GestureEvent::~GestureEvent() { -} +GestureEvent::GestureEvent(const GestureEvent& other) = default; + +GestureEvent::~GestureEvent() = default; } // namespace ui
diff --git a/ui/events/event.h b/ui/events/event.h index 7d972fcf..6830e8a 100644 --- a/ui/events/event.h +++ b/ui/events/event.h
@@ -51,6 +51,8 @@ class EVENTS_EXPORT Event { public: + // Copies an arbitrary event. If you have a typed event (e.g. a MouseEvent) + // just use its copy constructor. static std::unique_ptr<Event> Clone(const Event& event); virtual ~Event(); @@ -390,6 +392,8 @@ protected: friend class LocatedEventTestApi; + LocatedEvent(const LocatedEvent& copy); + explicit LocatedEvent(const base::NativeEvent& native_event); // Create a new LocatedEvent which is identical to the provided model. @@ -496,6 +500,8 @@ public: static const PointerId kMousePointerId; + // NOTE: On some platforms this will allow an event to be constructed from a + // void*, see base::NativeEvent. explicit MouseEvent(const base::NativeEvent& native_event); // |pointer_event.IsMousePointerEvent()| must be true. @@ -539,6 +545,9 @@ PointerDetails(EventPointerType::POINTER_TYPE_MOUSE, kMousePointerId)); + MouseEvent(const MouseEvent& copy); + ~MouseEvent() override; + // Conveniences to quickly test what button is down bool IsOnlyLeftMouseButton() const { return button_flags() == EF_LEFT_MOUSE_BUTTON; @@ -635,7 +644,8 @@ explicit MouseWheelEvent(const ScrollEvent& scroll_event); explicit MouseWheelEvent(const PointerEvent& pointer_event); MouseWheelEvent(const MouseEvent& mouse_event, int x_offset, int y_offset); - MouseWheelEvent(const MouseWheelEvent& mouse_wheel_event); + MouseWheelEvent(const MouseWheelEvent& copy); + ~MouseWheelEvent() override; template <class T> MouseWheelEvent(const MouseWheelEvent& model, @@ -998,6 +1008,9 @@ int finger_count, EventMomentumPhase momentum_phase = EventMomentumPhase::NONE); + ScrollEvent(const ScrollEvent& copy); + ~ScrollEvent() override; + // Scale the scroll event's offset value. // This is useful in the multi-monitor setup where it needs to be scaled // to provide a consistent user experience. @@ -1044,7 +1057,7 @@ : LocatedEvent(model, source, target), details_(model.details_) { } - + GestureEvent(const GestureEvent& copy); ~GestureEvent() override; const GestureEventDetails& details() const { return details_; }
diff --git a/ui/events/gestures/blink/web_gesture_curve_impl.cc b/ui/events/gestures/blink/web_gesture_curve_impl.cc index e8460be..65f680e 100644 --- a/ui/events/gestures/blink/web_gesture_curve_impl.cc +++ b/ui/events/gestures/blink/web_gesture_curve_impl.cc
@@ -88,8 +88,9 @@ WebGestureCurveImpl::~WebGestureCurveImpl() {} -bool WebGestureCurveImpl::Apply(double time, - blink::WebGestureCurveTarget* target) { +bool WebGestureCurveImpl::Advance(double time, + gfx::Vector2dF& out_current_velocity, + gfx::Vector2dF& out_delta_to_scroll) { // If the fling has yet to start, simply return and report true to prevent // fling termination. if (time <= 0) @@ -107,23 +108,14 @@ const base::TimeTicks time_ticks = base::TimeTicks() + base::TimeDelta::FromSecondsD(time); - gfx::Vector2dF offset, velocity; + gfx::Vector2dF offset; bool still_active = - curve_->ComputeScrollOffset(time_ticks, &offset, &velocity); + curve_->ComputeScrollOffset(time_ticks, &offset, &out_current_velocity); - gfx::Vector2dF delta = offset - last_offset_; + out_delta_to_scroll = offset - last_offset_; last_offset_ = offset; - // As successive timestamps can be arbitrarily close (but monotonic!), don't - // assume that a zero delta means the curve has terminated. - if (delta.IsZero()) - return still_active; - - // scrollBy() could delete this curve if the animation is over, so don't touch - // any member variables after making that call. - bool did_scroll = target->ScrollBy(blink::WebFloatSize(delta), - blink::WebFloatSize(velocity)); - return did_scroll && still_active; + return still_active; } } // namespace ui
diff --git a/ui/events/gestures/blink/web_gesture_curve_impl.h b/ui/events/gestures/blink/web_gesture_curve_impl.h index ecadeeb..4480fdcf 100644 --- a/ui/events/gestures/blink/web_gesture_curve_impl.h +++ b/ui/events/gestures/blink/web_gesture_curve_impl.h
@@ -15,10 +15,6 @@ #include "third_party/WebKit/public/platform/WebGestureDevice.h" #include "ui/gfx/geometry/vector2d_f.h" -namespace blink { -class WebGestureCurveTarget; -} - namespace ui { class GestureCurve; @@ -36,7 +32,9 @@ ~WebGestureCurveImpl() override; // WebGestureCurve implementation. - bool Apply(double time, blink::WebGestureCurveTarget* target) override; + bool Advance(double time, + gfx::Vector2dF& out_current_velocity, + gfx::Vector2dF& out_delta_to_scroll) override; private: enum class ThreadType {
diff --git a/ui/events/gestures/blink/web_gesture_curve_impl_unittest.cc b/ui/events/gestures/blink/web_gesture_curve_impl_unittest.cc index 33bc106..c5c6cfa 100644 --- a/ui/events/gestures/blink/web_gesture_curve_impl_unittest.cc +++ b/ui/events/gestures/blink/web_gesture_curve_impl_unittest.cc
@@ -49,22 +49,23 @@ // coded into the create call above. MockGestureCurveTarget target; - EXPECT_TRUE(curve->Apply(0, &target)); - EXPECT_TRUE(curve->Apply(0.25, &target)); + EXPECT_TRUE(curve->AdvanceAndApplyToTarget(0, &target)); + EXPECT_TRUE(curve->AdvanceAndApplyToTarget(0.25, &target)); EXPECT_NEAR(target.current_velocity().width, 1878, 1); EXPECT_EQ(target.current_velocity().height, 0); EXPECT_GT(target.cumulative_delta().width, 0); - EXPECT_TRUE(curve->Apply(0.45, &target)); // Use non-uniform tick spacing. + EXPECT_TRUE(curve->AdvanceAndApplyToTarget( + 0.45, &target)); // Use non-uniform tick spacing. // Ensure fling persists even if successive timestamps are identical. gfx::Vector2dF cumulative_delta = target.cumulative_delta(); gfx::Vector2dF current_velocity = target.current_velocity(); - EXPECT_TRUE(curve->Apply(0.45, &target)); + EXPECT_TRUE(curve->AdvanceAndApplyToTarget(0.45, &target)); EXPECT_EQ(cumulative_delta, gfx::Vector2dF(target.cumulative_delta())); EXPECT_EQ(current_velocity, gfx::Vector2dF(target.current_velocity())); - EXPECT_TRUE(curve->Apply(0.75, &target)); - EXPECT_FALSE(curve->Apply(1.5, &target)); + EXPECT_TRUE(curve->AdvanceAndApplyToTarget(0.75, &target)); + EXPECT_FALSE(curve->AdvanceAndApplyToTarget(1.5, &target)); EXPECT_NEAR(target.cumulative_delta().width, 1193, 1); EXPECT_EQ(target.cumulative_delta().height, 0); EXPECT_EQ(target.current_velocity().width, 0);
diff --git a/ui/gfx/OWNERS b/ui/gfx/OWNERS index cf44bc1..ad40b66f 100644 --- a/ui/gfx/OWNERS +++ b/ui/gfx/OWNERS
@@ -1,9 +1,6 @@ # Font rendering and what not. asvitkine@chromium.org -# Primitive graphics types (size, rect, vector ...) -danakj@chromium.org - # RenderText and related classes. msw@chromium.org @@ -14,8 +11,13 @@ # Font-rendering configuration. per-file font_render_params*=derat@chromium.org +# Canvas painting. +per-file canvas*=danakj@chromium.org + # Transform, interpolated transform and transform util. +per-file transform*=danakj@chromium.org per-file transform*=vollick@chromium.org +per-file interpolated_transform*=danakj@chromium.org per-file interpolated_transform*=vollick@chromium.org # GPU memory buffer and GpuFence interfaces.
diff --git a/ui/keyboard/keyboard_util.h b/ui/keyboard/keyboard_util.h index 127723f8..fafda56a 100644 --- a/ui/keyboard/keyboard_util.h +++ b/ui/keyboard/keyboard_util.h
@@ -14,8 +14,6 @@ class WindowTreeHost; } -class GURL; - namespace keyboard { // For virtual keyboard IME extension. @@ -172,13 +170,6 @@ // keyboard is loaded. KEYBOARD_EXPORT void MarkKeyboardLoadFinished(); -// Sets the override content url. -// This is used by for input view for extension IMEs. -KEYBOARD_EXPORT void SetOverrideContentUrl(const GURL& url); - -// Gets the override content url. -KEYBOARD_EXPORT const GURL& GetOverrideContentUrl(); - // Logs the keyboard control event as a UMA stat. void LogKeyboardControlEvent(KeyboardControlEvent event);
diff --git a/ui/message_center/views/notification_button.cc b/ui/message_center/views/notification_button.cc index e742faf..f4110cc 100644 --- a/ui/message_center/views/notification_button.cc +++ b/ui/message_center/views/notification_button.cc
@@ -24,7 +24,7 @@ // background changes to show touch feedback SetBackground(views::CreateSolidBackground(kNotificationBackgroundColor)); set_notify_enter_exit_on_child(true); - SetLayoutManager(new views::BoxLayout( + SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::kHorizontal, gfx::Insets(kButtonVerticalPadding, message_center::kButtonHorizontalPadding),
diff --git a/ui/message_center/views/notification_control_buttons_view.cc b/ui/message_center/views/notification_control_buttons_view.cc index 06ddf4d..b4fb713 100644 --- a/ui/message_center/views/notification_control_buttons_view.cc +++ b/ui/message_center/views/notification_control_buttons_view.cc
@@ -44,7 +44,8 @@ bgcolor_origin_(kInitialBackgroundColor), bgcolor_target_(kInitialBackgroundColor) { DCHECK(message_view); - SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal)); + SetLayoutManager( + std::make_unique<views::BoxLayout>(views::BoxLayout::kHorizontal)); // Use layer to change the opacity. SetPaintToLayer();
diff --git a/ui/message_center/views/notification_header_view.cc b/ui/message_center/views/notification_header_view.cc index c537e36c..d6f7a7e5 100644 --- a/ui/message_center/views/notification_header_view.cc +++ b/ui/message_center/views/notification_header_view.cc
@@ -165,19 +165,18 @@ : views::Button(listener) { const int kInnerHeaderHeight = kHeaderHeight - kHeaderOuterPadding.height(); - views::BoxLayout* layout = - new views::BoxLayout(views::BoxLayout::kHorizontal, kHeaderOuterPadding, - kHeaderHorizontalSpacing); + auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::kHorizontal, kHeaderOuterPadding, + kHeaderHorizontalSpacing)); layout->set_cross_axis_alignment( views::BoxLayout::CROSS_AXIS_ALIGNMENT_START); - SetLayoutManager(layout); views::View* app_info_container = new views::View(); - views::BoxLayout* app_info_layout = new views::BoxLayout( + auto app_info_layout = std::make_unique<views::BoxLayout>( views::BoxLayout::kHorizontal, kHeaderPadding, kHeaderHorizontalSpacing); app_info_layout->set_cross_axis_alignment( views::BoxLayout::CROSS_AXIS_ALIGNMENT_START); - app_info_container->SetLayoutManager(app_info_layout); + app_info_container->SetLayoutManager(std::move(app_info_layout)); AddChildView(app_info_container); // App icon view
diff --git a/ui/message_center/views/notification_view.cc b/ui/message_center/views/notification_view.cc index 3b9f3b2..8b34638 100644 --- a/ui/message_center/views/notification_view.cc +++ b/ui/message_center/views/notification_view.cc
@@ -101,9 +101,9 @@ }; NotificationItemView::NotificationItemView(const NotificationItem& item) { - SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, - gfx::Insets(), - kItemTitleToMessagePadding)); + SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::kHorizontal, gfx::Insets(), + kItemTitleToMessagePadding)); views::Label* title = new views::Label(item.title); title->set_collapse_when_hidden(true); @@ -182,7 +182,7 @@ // close button. top_view_ = new views::View(); top_view_->SetLayoutManager( - new views::BoxLayout(views::BoxLayout::kVertical)); + std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); top_view_->SetBorder( MakeEmptyBorder(kTextTopPadding - 8, 0, kTextBottomPadding - 5, 0)); AddChildView(top_view_); @@ -190,7 +190,7 @@ // below the notification icon. bottom_view_ = new views::View(); bottom_view_->SetLayoutManager( - new views::BoxLayout(views::BoxLayout::kVertical)); + std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); AddChildView(bottom_view_); control_buttons_view_ = new NotificationControlButtonsView(this); @@ -565,7 +565,7 @@ DCHECK_EQ(this, bottom_view_->parent()); image_container_ = new views::View(); - image_container_->SetLayoutManager(new views::FillLayout()); + image_container_->SetLayoutManager(std::make_unique<views::FillLayout>()); image_container_->SetBackground( views::CreateSolidBackground(kImageBackgroundColor));
diff --git a/ui/message_center/views/notification_view_md.cc b/ui/message_center/views/notification_view_md.cc index 916cff7..cda4aa0 100644 --- a/ui/message_center/views/notification_view_md.cc +++ b/ui/message_center/views/notification_view_md.cc
@@ -147,8 +147,8 @@ // ItemView //////////////////////////////////////////////////////////////////// ItemView::ItemView(const message_center::NotificationItem& item) { - SetLayoutManager( - new views::BoxLayout(views::BoxLayout::kHorizontal, gfx::Insets(), 0)); + SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::kHorizontal, gfx::Insets(), 0)); const gfx::FontList font_list = GetTextFontList(); @@ -185,7 +185,7 @@ } CompactTitleMessageView::CompactTitleMessageView() { - SetLayoutManager(new views::FillLayout()); + SetLayoutManager(std::make_unique<views::FillLayout>()); const gfx::FontList& font_list = GetTextFontList(); @@ -295,7 +295,7 @@ LargeImageContainerView::LargeImageContainerView() : image_view_(new LargeImageView()) { - SetLayoutManager(new views::FillLayout()); + SetLayoutManager(std::make_unique<views::FillLayout>()); SetBorder(views::CreateEmptyBorder(kLargeImageContainerPadding)); SetBackground( views::CreateSolidBackground(message_center::kImageBackgroundColor)); @@ -440,8 +440,8 @@ NotificationViewMD::NotificationViewMD(const Notification& notification) : MessageView(notification), clickable_(notification.clickable()) { - SetLayoutManager( - new views::BoxLayout(views::BoxLayout::kVertical, gfx::Insets(), 0)); + SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::kVertical, gfx::Insets(), 0)); control_buttons_view_ = std::make_unique<NotificationControlButtonsView>(this); @@ -454,37 +454,37 @@ // |content_row_| contains title, message, image, progressbar, etc... content_row_ = new views::View(); - views::BoxLayout* content_row_layout = new views::BoxLayout( - views::BoxLayout::kHorizontal, kContentRowPadding, 0); + auto* content_row_layout = + content_row_->SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::kHorizontal, kContentRowPadding, 0)); content_row_layout->set_cross_axis_alignment( views::BoxLayout::CROSS_AXIS_ALIGNMENT_START); - content_row_->SetLayoutManager(content_row_layout); AddChildView(content_row_); // |left_content_| contains most contents like title, message, etc... left_content_ = new views::View(); - left_content_->SetLayoutManager( - new views::BoxLayout(views::BoxLayout::kVertical, gfx::Insets(), 0)); + left_content_->SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::kVertical, gfx::Insets(), 0)); left_content_->SetBorder(views::CreateEmptyBorder(kLeftContentPadding)); content_row_->AddChildView(left_content_); content_row_layout->SetFlexForView(left_content_, 1); // |right_content_| contains notification icon and small image. right_content_ = new views::View(); - right_content_->SetLayoutManager(new views::FillLayout()); + right_content_->SetLayoutManager(std::make_unique<views::FillLayout>()); content_row_->AddChildView(right_content_); // |action_row_| contains inline action buttons and inline textfield. actions_row_ = new views::View(); actions_row_->SetVisible(false); - actions_row_->SetLayoutManager(new views::FillLayout()); + actions_row_->SetLayoutManager(std::make_unique<views::FillLayout>()); AddChildView(actions_row_); // |action_buttons_row_| contains inline action buttons. action_buttons_row_ = new views::View(); - action_buttons_row_->SetLayoutManager( - new views::BoxLayout(views::BoxLayout::kHorizontal, kActionsRowPadding, - kActionsRowHorizontalSpacing)); + action_buttons_row_->SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::kHorizontal, kActionsRowPadding, + kActionsRowHorizontalSpacing)); action_buttons_row_->SetBackground( views::CreateSolidBackground(kActionsRowBackgroundColor)); action_buttons_row_->SetVisible(false);
diff --git a/ui/ozone/platform/drm/gpu/gbm_buffer.cc b/ui/ozone/platform/drm/gpu/gbm_buffer.cc index 7dfb1fe..54e74b1b 100644 --- a/ui/ozone/platform/drm/gpu/gbm_buffer.cc +++ b/ui/ozone/platform/drm/gpu/gbm_buffer.cc
@@ -80,9 +80,9 @@ gbm_bo_get_num_planes(bo), gbm_bo_get_width(bo), gbm_bo_get_height(bo), addfb_flags); for (size_t i = 0; i < gbm_bo_get_num_planes(bo); ++i) { - LOG(ERROR) << base::StringPrintf( - "handle: %u, stride: %u, offset: %u, modifier: %zu", handles[i], - strides[i], offsets[i], modifiers[i]); + LOG(ERROR) << "handles: " << handles[i] << ", stride: " << strides[i] + << ", offset: " << offsets[i] + << ", modifier: " << modifiers[i]; } } DCHECK(ret);
diff --git a/ui/views/accessible_pane_view_unittest.cc b/ui/views/accessible_pane_view_unittest.cc index 4d0bb587..7aef74a 100644 --- a/ui/views/accessible_pane_view_unittest.cc +++ b/ui/views/accessible_pane_view_unittest.cc
@@ -57,7 +57,7 @@ } void TestBarView::Init() { - SetLayoutManager(new FillLayout()); + SetLayoutManager(std::make_unique<FillLayout>()); base::string16 label; child_button_.reset(new LabelButton(this, label)); AddChildView(child_button_.get());
diff --git a/ui/views/bubble/bubble_frame_view.cc b/ui/views/bubble/bubble_frame_view.cc index 0d9ec53..67bc8ae 100644 --- a/ui/views/bubble/bubble_frame_view.cc +++ b/ui/views/bubble/bubble_frame_view.cc
@@ -462,7 +462,7 @@ DCHECK(!footnote_container_); footnote_container_ = new FootnoteContainerView(); footnote_container_->SetLayoutManager( - new BoxLayout(BoxLayout::kVertical, footnote_margins_, 0)); + std::make_unique<BoxLayout>(BoxLayout::kVertical, footnote_margins_, 0)); footnote_container_->SetBackground( CreateSolidBackground(kFootnoteBackgroundColor)); footnote_container_->SetBorder(
diff --git a/ui/views/bubble/info_bubble.cc b/ui/views/bubble/info_bubble.cc index 6e315235..b17c6db 100644 --- a/ui/views/bubble/info_bubble.cc +++ b/ui/views/bubble/info_bubble.cc
@@ -56,7 +56,7 @@ gfx::Insets(kInfoBubbleVerticalMargin, kInfoBubbleHorizontalMargin)); set_can_activate(false); - SetLayoutManager(new FillLayout); + SetLayoutManager(std::make_unique<FillLayout>()); Label* label = new Label(message); label->SetHorizontalAlignment(gfx::ALIGN_LEFT); label->SetMultiLine(true);
diff --git a/ui/views/bubble/tray_bubble_view.cc b/ui/views/bubble/tray_bubble_view.cc index da70390d..392cbd1 100644 --- a/ui/views/bubble/tray_bubble_view.cc +++ b/ui/views/bubble/tray_bubble_view.cc
@@ -205,7 +205,7 @@ : BubbleDialogDelegateView(init_params.anchor_view, GetArrowAlignment(init_params.anchor_alignment)), params_(init_params), - layout_(new BottomAlignedBoxLayout(this)), + layout_(nullptr), delegate_(init_params.delegate), preferred_width_(init_params.min_width), bubble_border_(new BubbleBorder( @@ -232,8 +232,9 @@ views::Painter::CreateSolidRoundRectPainter( SK_ColorBLACK, bubble_border_->GetBorderCornerRadius())); - layout_->SetDefaultFlex(1); - SetLayoutManager(layout_); + auto layout = std::make_unique<BottomAlignedBoxLayout>(this); + layout->SetDefaultFlex(1); + layout_ = SetLayoutManager(std::move(layout)); } TrayBubbleView::~TrayBubbleView() {
diff --git a/ui/views/cocoa/DEPS b/ui/views/cocoa/DEPS index c7623d9..3209b5a 100644 --- a/ui/views/cocoa/DEPS +++ b/ui/views/cocoa/DEPS
@@ -1,3 +1,4 @@ include_rules = [ + "+components/viz/common", "+ui/accelerated_widget_mac", ]
diff --git a/ui/views/cocoa/bridged_native_widget.mm b/ui/views/cocoa/bridged_native_widget.mm index 520e006..9e3a909 100644 --- a/ui/views/cocoa/bridged_native_widget.mm +++ b/ui/views/cocoa/bridged_native_widget.mm
@@ -15,6 +15,7 @@ #include "base/memory/ptr_util.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" +#include "components/viz/common/features.h" #include "ui/accelerated_widget_mac/window_resize_helper_mac.h" #import "ui/base/cocoa/constrained_window/constrained_window_animation.h" #include "ui/base/hit_test.h" @@ -1402,7 +1403,7 @@ compositor_.reset(new ui::Compositor( context_factory_private->AllocateFrameSinkId(), context_factory, context_factory_private, GetCompositorTaskRunner(), - false /* enable_surface_synchronization */, + features::IsSurfaceSynchronizationEnabled(), ui::IsPixelCanvasRecordingEnabled())); compositor_->SetAcceleratedWidget(compositor_widget_->accelerated_widget()); compositor_widget_->SetNSView(this);
diff --git a/ui/views/color_chooser/color_chooser_view.cc b/ui/views/color_chooser/color_chooser_view.cc index 531e121..f0822826 100644 --- a/ui/views/color_chooser/color_chooser_view.cc +++ b/ui/views/color_chooser/color_chooser_view.cc
@@ -364,12 +364,12 @@ DCHECK(listener_); SetBackground(CreateSolidBackground(SK_ColorLTGRAY)); - SetLayoutManager(new BoxLayout(BoxLayout::kVertical, - gfx::Insets(kMarginWidth), kMarginWidth)); + SetLayoutManager(std::make_unique<BoxLayout>( + BoxLayout::kVertical, gfx::Insets(kMarginWidth), kMarginWidth)); View* container = new View(); - container->SetLayoutManager( - new BoxLayout(BoxLayout::kHorizontal, gfx::Insets(), kMarginWidth)); + container->SetLayoutManager(std::make_unique<BoxLayout>( + BoxLayout::kHorizontal, gfx::Insets(), kMarginWidth)); saturation_value_ = new SaturationValueView(this); container->AddChildView(saturation_value_); hue_ = new HueView(this); @@ -377,7 +377,8 @@ AddChildView(container); View* container2 = new View(); - GridLayout* layout = GridLayout::CreateAndInstall(container2); + GridLayout* layout = container2->SetLayoutManager( + std::make_unique<views::GridLayout>(container2)); ColumnSet* columns = layout->AddColumnSet(0); columns->AddColumn( GridLayout::LEADING, GridLayout::FILL, 0, GridLayout::USE_PREF, 0, 0);
diff --git a/ui/views/controls/message_box_view.cc b/ui/views/controls/message_box_view.cc index 90fb81c..5b0a00a 100644 --- a/ui/views/controls/message_box_view.cc +++ b/ui/views/controls/message_box_view.cc
@@ -218,7 +218,8 @@ void MessageBoxView::ResetLayoutManager() { // Initialize the Grid Layout Manager used for this dialog box. - GridLayout* layout = GridLayout::CreateAndInstall(this); + GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); // Add the column set for the message displayed at the top of the dialog box. constexpr int kMessageViewColumnSetId = 0; @@ -247,7 +248,7 @@ // so that the scroll view borders are not capped by dialog insets. message_contents->SetBorder(CreateEmptyBorder(horizontal_insets)); message_contents->SetLayoutManager( - new views::BoxLayout(views::BoxLayout::kVertical)); + std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical)); for (size_t i = 0; i < message_labels_.size(); ++i) message_contents->AddChildView(message_labels_[i]); ScrollView* scroll_view = new views::ScrollView();
diff --git a/ui/views/controls/tabbed_pane/tabbed_pane.cc b/ui/views/controls/tabbed_pane/tabbed_pane.cc index b540db4..bff1a9c4 100644 --- a/ui/views/controls/tabbed_pane/tabbed_pane.cc +++ b/ui/views/controls/tabbed_pane/tabbed_pane.cc
@@ -136,7 +136,7 @@ SetBorder(CreateEmptyBorder( gfx::Insets(kTabVerticalPadding, kTabHorizontalPadding))); - SetLayoutManager(new FillLayout); + SetLayoutManager(std::make_unique<FillLayout>()); SetState(TAB_INACTIVE); AddChildView(title_); @@ -323,12 +323,12 @@ TabStrip::TabStrip() { const int kTabStripLeadingEdgePadding = 9; - BoxLayout* layout = new BoxLayout( + auto layout = std::make_unique<BoxLayout>( BoxLayout::kHorizontal, gfx::Insets(0, kTabStripLeadingEdgePadding)); layout->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_START); layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_END); layout->SetDefaultFlex(0); - SetLayoutManager(layout); + SetLayoutManager(std::move(layout)); } TabStrip::~TabStrip() {} @@ -395,11 +395,11 @@ } MdTabStrip::MdTabStrip() { - BoxLayout* layout = new BoxLayout(BoxLayout::kHorizontal); + auto layout = std::make_unique<BoxLayout>(BoxLayout::kHorizontal); layout->set_main_axis_alignment(BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER); layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_STRETCH); layout->SetDefaultFlex(1); - SetLayoutManager(layout); + SetLayoutManager(std::move(layout)); // These durations are taken from the Paper Tabs source: // https://github.com/PolymerElements/paper-tabs/blob/master/paper-tabs.html
diff --git a/ui/views/controls/webview/web_dialog_view.cc b/ui/views/controls/webview/web_dialog_view.cc index ae334eee..ba3480d 100644 --- a/ui/views/controls/webview/web_dialog_view.cc +++ b/ui/views/controls/webview/web_dialog_view.cc
@@ -46,7 +46,7 @@ web_view_->set_allow_accelerators(true); AddChildView(web_view_); set_contents_view(web_view_); - SetLayoutManager(new views::FillLayout); + SetLayoutManager(std::make_unique<views::FillLayout>()); // Pressing the ESC key will close the dialog. AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
diff --git a/ui/views/examples/box_layout_example.cc b/ui/views/examples/box_layout_example.cc index 7628b9b..e3697cd 100644 --- a/ui/views/examples/box_layout_example.cc +++ b/ui/views/examples/box_layout_example.cc
@@ -279,7 +279,7 @@ } void BoxLayoutExample::CreateExampleView(View* container) { - container->SetLayoutManager(new FillLayout()); + container->SetLayoutManager(std::make_unique<FillLayout>()); full_panel_ = new FullPanel(); container->AddChildView(full_panel_); @@ -412,18 +412,18 @@ base::StringToInt(between_child_spacing_->text(), &child_spacing); base::StringToInt(default_flex_->text(), &default_flex); base::StringToInt(min_cross_axis_size_->text(), &min_cross_size); - layout_ = new BoxLayout( + auto layout = std::make_unique<BoxLayout>( orientation_->selected_index() == 0 ? BoxLayout::Orientation::kHorizontal : BoxLayout::Orientation::kVertical, gfx::Insets(0, 0), child_spacing, collapse_margins_->checked()); - layout_->set_cross_axis_alignment(static_cast<BoxLayout::CrossAxisAlignment>( + layout->set_cross_axis_alignment(static_cast<BoxLayout::CrossAxisAlignment>( cross_axis_alignment_->selected_index())); - layout_->set_main_axis_alignment(static_cast<BoxLayout::MainAxisAlignment>( + layout->set_main_axis_alignment(static_cast<BoxLayout::MainAxisAlignment>( main_axis_alignment_->selected_index())); - layout_->SetDefaultFlex(default_flex); - layout_->set_minimum_cross_axis_size(min_cross_size); + layout->SetDefaultFlex(default_flex); + layout->set_minimum_cross_axis_size(min_cross_size); UpdateBorderInsets(); - box_layout_panel_->SetLayoutManager(layout_); + layout_ = box_layout_panel_->SetLayoutManager(std::move(layout)); for (int i = 0; i < box_layout_panel_->child_count(); ++i) { ChildPanel* panel = static_cast<ChildPanel*>(box_layout_panel_->child_at(i));
diff --git a/ui/views/examples/bubble_example.cc b/ui/views/examples/bubble_example.cc index 6f21b7a..026a1032 100644 --- a/ui/views/examples/bubble_example.cc +++ b/ui/views/examples/bubble_example.cc
@@ -59,7 +59,8 @@ int GetDialogButtons() const override { return ui::DIALOG_BUTTON_NONE; } void Init() override { - SetLayoutManager(new BoxLayout(BoxLayout::kVertical, gfx::Insets(50))); + SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(50))); AddChildView(new Label(GetArrowName(arrow()))); } @@ -77,7 +78,7 @@ PrintStatus("Click with optional modifiers: [Ctrl] for set_arrow(NONE), " "[Alt] for set_arrow(FLOAT), or [Shift] to reverse the arrow iteration."); container->SetLayoutManager( - new BoxLayout(BoxLayout::kHorizontal, gfx::Insets(), 10)); + std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(), 10)); no_shadow_ = new LabelButton(this, ASCIIToUTF16("No Shadow")); container->AddChildView(no_shadow_); no_shadow_opaque_ = new LabelButton(this, ASCIIToUTF16("Opaque Border"));
diff --git a/ui/views/examples/button_example.cc b/ui/views/examples/button_example.cc index 048ef485..37c31a2 100644 --- a/ui/views/examples/button_example.cc +++ b/ui/views/examples/button_example.cc
@@ -39,9 +39,10 @@ void ButtonExample::CreateExampleView(View* container) { container->SetBackground(CreateSolidBackground(SK_ColorWHITE)); - BoxLayout* layout = new BoxLayout(BoxLayout::kVertical, gfx::Insets(10), 10); + auto layout = + std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(10), 10); layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); - container->SetLayoutManager(layout); + container->SetLayoutManager(std::move(layout)); label_button_ = new LabelButton(this, ASCIIToUTF16(kLabelButton)); label_button_->SetFocusForPlatform();
diff --git a/ui/views/examples/button_sticker_sheet.cc b/ui/views/examples/button_sticker_sheet.cc index eb804408..b395387 100644 --- a/ui/views/examples/button_sticker_sheet.cc +++ b/ui/views/examples/button_sticker_sheet.cc
@@ -31,7 +31,8 @@ const GridLayout::SizeType kColumnUsesFixedSize = GridLayout::FIXED; const int kColumnWidth = 96; - GridLayout* layout = GridLayout::CreateAndInstall(host); + GridLayout* layout = + host->SetLayoutManager(std::make_unique<views::GridLayout>(host)); ColumnSet* columns = layout->AddColumnSet(kStretchyGridColumnSetId); for (int i = 0; i < ncols; ++i) { if (i != 0)
diff --git a/ui/views/examples/checkbox_example.cc b/ui/views/examples/checkbox_example.cc index b25dd8e..b28a6b6 100644 --- a/ui/views/examples/checkbox_example.cc +++ b/ui/views/examples/checkbox_example.cc
@@ -22,7 +22,7 @@ void CheckboxExample::CreateExampleView(View* container) { button_ = new Checkbox(base::ASCIIToUTF16("Checkbox")); button_->set_listener(this); - container->SetLayoutManager(new FillLayout); + container->SetLayoutManager(std::make_unique<FillLayout>()); container->AddChildView(button_); }
diff --git a/ui/views/examples/combobox_example.cc b/ui/views/examples/combobox_example.cc index 8fd871b..ff46b875 100644 --- a/ui/views/examples/combobox_example.cc +++ b/ui/views/examples/combobox_example.cc
@@ -56,7 +56,7 @@ // default. container->SetLayoutManager( - new BoxLayout(BoxLayout::kVertical, gfx::Insets(10, 0), 5)); + std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(10, 0), 5)); container->AddChildView(combobox_); container->AddChildView(disabled_combobox_); container->AddChildView(action_combobox_);
diff --git a/ui/views/examples/dialog_example.cc b/ui/views/examples/dialog_example.cc index 838bccb..97737f1 100644 --- a/ui/views/examples/dialog_example.cc +++ b/ui/views/examples/dialog_example.cc
@@ -37,8 +37,7 @@ explicit Delegate(DialogExample* parent) : parent_(parent) {} void InitDelegate() { - LayoutManager* fill_layout = new FillLayout(); - this->SetLayoutManager(fill_layout); + this->SetLayoutManager(std::make_unique<FillLayout>()); Label* body = new Label(parent_->body_->text()); body->SetMultiLine(true); body->SetHorizontalAlignment(gfx::ALIGN_LEFT); @@ -133,7 +132,8 @@ views::LayoutProvider* provider = views::LayoutProvider::Get(); const int horizontal_spacing = provider->GetDistanceMetric(views::DISTANCE_RELATED_BUTTON_HORIZONTAL); - GridLayout* layout = GridLayout::CreateAndInstall(container); + GridLayout* layout = container->SetLayoutManager( + std::make_unique<views::GridLayout>(container)); ColumnSet* column_set = layout->AddColumnSet(kFieldsColumnId); column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, kFixed, GridLayout::USE_PREF, 0, 0);
diff --git a/ui/views/examples/examples_window.cc b/ui/views/examples/examples_window.cc index add00ef..e6b46660 100644 --- a/ui/views/examples/examples_window.cc +++ b/ui/views/examples/examples_window.cc
@@ -143,7 +143,8 @@ combobox_->ModelChanged(); SetBackground(CreateStandardPanelBackground()); - GridLayout* layout = GridLayout::CreateAndInstall(this); + GridLayout* layout = + SetLayoutManager(std::make_unique<views::GridLayout>(this)); ColumnSet* column_set = layout->AddColumnSet(0); column_set->AddPaddingColumn(0, 5); column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, @@ -155,7 +156,7 @@ if (combobox_model_.GetItemCount() > 0) { layout->StartRow(1, 0); - example_shown_->SetLayoutManager(new FillLayout()); + example_shown_->SetLayoutManager(std::make_unique<FillLayout>()); example_shown_->AddChildView(combobox_model_.GetItemViewAt(0)); layout->AddView(example_shown_); }
diff --git a/ui/views/examples/label_example.cc b/ui/views/examples/label_example.cc index dbc8932..be6bbe92 100644 --- a/ui/views/examples/label_example.cc +++ b/ui/views/examples/label_example.cc
@@ -69,7 +69,7 @@ void LabelExample::CreateExampleView(View* container) { // A very simple label example, followed by additional helpful examples. container->SetLayoutManager( - new BoxLayout(BoxLayout::kVertical, gfx::Insets(), 10)); + std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(), 10)); Label* label = new Label(ASCIIToUTF16("Hello world!")); container->AddChildView(label); @@ -163,7 +163,8 @@ View* control_container = new View(); control_container->SetBorder(CreateSolidBorder(2, SK_ColorGRAY)); control_container->SetBackground(CreateSolidBackground(SK_ColorLTGRAY)); - GridLayout* layout = GridLayout::CreateAndInstall(control_container); + GridLayout* layout = control_container->SetLayoutManager( + std::make_unique<views::GridLayout>(control_container)); ColumnSet* column_set = layout->AddColumnSet(0); column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL,
diff --git a/ui/views/examples/link_example.cc b/ui/views/examples/link_example.cc index 3795c8c..19aa3ee 100644 --- a/ui/views/examples/link_example.cc +++ b/ui/views/examples/link_example.cc
@@ -22,7 +22,7 @@ link_ = new Link(base::ASCIIToUTF16("Click me!")); link_->set_listener(this); - container->SetLayoutManager(new FillLayout); + container->SetLayoutManager(std::make_unique<FillLayout>()); container->AddChildView(link_); }
diff --git a/ui/views/examples/menu_example.cc b/ui/views/examples/menu_example.cc index df66a42..2e9081c 100644 --- a/ui/views/examples/menu_example.cc +++ b/ui/views/examples/menu_example.cc
@@ -204,7 +204,7 @@ // We add a button to open a menu. ExampleMenuButton* menu_button = new ExampleMenuButton( ASCIIToUTF16("Open a menu")); - container->SetLayoutManager(new FillLayout); + container->SetLayoutManager(std::make_unique<FillLayout>()); container->AddChildView(menu_button); }
diff --git a/ui/views/examples/message_box_example.cc b/ui/views/examples/message_box_example.cc index 3327ff9..81463c2 100644 --- a/ui/views/examples/message_box_example.cc +++ b/ui/views/examples/message_box_example.cc
@@ -27,7 +27,8 @@ status_ = new LabelButton(this, ASCIIToUTF16("Show Status")); toggle_ = new LabelButton(this, ASCIIToUTF16("Toggle Checkbox")); - GridLayout* layout = GridLayout::CreateAndInstall(container); + GridLayout* layout = container->SetLayoutManager( + std::make_unique<views::GridLayout>(container)); message_box_view_->SetCheckBoxLabel(ASCIIToUTF16("Check Box"));
diff --git a/ui/views/examples/multiline_example.cc b/ui/views/examples/multiline_example.cc index 46da3ea..4e5225bd 100644 --- a/ui/views/examples/multiline_example.cc +++ b/ui/views/examples/multiline_example.cc
@@ -159,7 +159,8 @@ textfield_->set_controller(this); textfield_->SetText(kTestString); - GridLayout* layout = GridLayout::CreateAndInstall(container); + GridLayout* layout = container->SetLayoutManager( + std::make_unique<views::GridLayout>(container)); ColumnSet* column_set = layout->AddColumnSet(0); column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
diff --git a/ui/views/examples/progress_bar_example.cc b/ui/views/examples/progress_bar_example.cc index c9d82665..610ce9a 100644 --- a/ui/views/examples/progress_bar_example.cc +++ b/ui/views/examples/progress_bar_example.cc
@@ -36,7 +36,8 @@ } void ProgressBarExample::CreateExampleView(View* container) { - GridLayout* layout = GridLayout::CreateAndInstall(container); + GridLayout* layout = container->SetLayoutManager( + std::make_unique<views::GridLayout>(container)); ColumnSet* column_set = layout->AddColumnSet(0); column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
diff --git a/ui/views/examples/radio_button_example.cc b/ui/views/examples/radio_button_example.cc index e0daa38f..4f6e05b 100644 --- a/ui/views/examples/radio_button_example.cc +++ b/ui/views/examples/radio_button_example.cc
@@ -38,7 +38,8 @@ radio_buttons_[i]->set_listener(this); } - GridLayout* layout = GridLayout::CreateAndInstall(container); + GridLayout* layout = container->SetLayoutManager( + std::make_unique<views::GridLayout>(container)); ColumnSet* column_set = layout->AddColumnSet(0); column_set->AddColumn(GridLayout::FILL, GridLayout::FILL,
diff --git a/ui/views/examples/scroll_view_example.cc b/ui/views/examples/scroll_view_example.cc index ef6ff41..8dbebef9 100644 --- a/ui/views/examples/scroll_view_example.cc +++ b/ui/views/examples/scroll_view_example.cc
@@ -87,7 +87,8 @@ scrollable_->SetBounds(0, 0, 1000, 100); scrollable_->SetColor(SK_ColorYELLOW, SK_ColorCYAN); - GridLayout* layout = GridLayout::CreateAndInstall(container); + GridLayout* layout = container->SetLayoutManager( + std::make_unique<views::GridLayout>(container)); // Add scroll view. ColumnSet* column_set = layout->AddColumnSet(0);
diff --git a/ui/views/examples/slider_example.cc b/ui/views/examples/slider_example.cc index 4bc4820..d08b944 100644 --- a/ui/views/examples/slider_example.cc +++ b/ui/views/examples/slider_example.cc
@@ -31,7 +31,7 @@ slider_->SetValue(0.5); container->SetLayoutManager( - new BoxLayout(BoxLayout::kHorizontal, gfx::Insets(3), 3)); + std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(3), 3)); container->AddChildView(slider_); container->AddChildView(label_); }
diff --git a/ui/views/examples/tabbed_pane_example.cc b/ui/views/examples/tabbed_pane_example.cc index 2623c10b..1c1bb2f 100644 --- a/ui/views/examples/tabbed_pane_example.cc +++ b/ui/views/examples/tabbed_pane_example.cc
@@ -27,7 +27,8 @@ add_at_ = new LabelButton(this, ASCIIToUTF16("Add At 1")); select_at_ = new LabelButton(this, ASCIIToUTF16("Select At 1")); - GridLayout* layout = GridLayout::CreateAndInstall(container); + GridLayout* layout = container->SetLayoutManager( + std::make_unique<views::GridLayout>(container)); const int tabbed_pane_column = 0; ColumnSet* column_set = layout->AddColumnSet(tabbed_pane_column);
diff --git a/ui/views/examples/table_example.cc b/ui/views/examples/table_example.cc index f3bd426..1fd544f 100644 --- a/ui/views/examples/table_example.cc +++ b/ui/views/examples/table_example.cc
@@ -58,7 +58,8 @@ column4_visible_checkbox_->SetChecked(true); column4_visible_checkbox_->set_listener(this); - GridLayout* layout = GridLayout::CreateAndInstall(container); + GridLayout* layout = container->SetLayoutManager( + std::make_unique<views::GridLayout>(container)); std::vector<ui::TableColumn> columns; columns.push_back(TestTableColumn(0, "Fruit"));
diff --git a/ui/views/examples/text_example.cc b/ui/views/examples/text_example.cc index d35e667fb..8b95cf23 100644 --- a/ui/views/examples/text_example.cc +++ b/ui/views/examples/text_example.cc
@@ -160,7 +160,8 @@ void TextExample::CreateExampleView(View* container) { text_view_ = new TextExampleView; text_view_->SetBorder(CreateSolidBorder(1, SK_ColorGRAY)); - GridLayout* layout = GridLayout::CreateAndInstall(container); + GridLayout* layout = container->SetLayoutManager( + std::make_unique<views::GridLayout>(container)); layout->AddPaddingRow(0, 8); ColumnSet* column_set = layout->AddColumnSet(0);
diff --git a/ui/views/examples/textfield_example.cc b/ui/views/examples/textfield_example.cc index e166ac0..6e4c5fe 100644 --- a/ui/views/examples/textfield_example.cc +++ b/ui/views/examples/textfield_example.cc
@@ -61,7 +61,8 @@ name_->set_controller(this); password_->set_controller(this); - GridLayout* layout = GridLayout::CreateAndInstall(container); + GridLayout* layout = container->SetLayoutManager( + std::make_unique<views::GridLayout>(container)); ColumnSet* column_set = layout->AddColumnSet(0); column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL,
diff --git a/ui/views/examples/throbber_example.cc b/ui/views/examples/throbber_example.cc index 7c513972..c95a04e4 100644 --- a/ui/views/examples/throbber_example.cc +++ b/ui/views/examples/throbber_example.cc
@@ -63,7 +63,7 @@ } void ThrobberExample::CreateExampleView(View* container) { - container->SetLayoutManager(new FillLayout()); + container->SetLayoutManager(std::make_unique<FillLayout>()); container->AddChildView(new ThrobberView()); }
diff --git a/ui/views/examples/toggle_button_example.cc b/ui/views/examples/toggle_button_example.cc index 7cec6167..29c691b 100644 --- a/ui/views/examples/toggle_button_example.cc +++ b/ui/views/examples/toggle_button_example.cc
@@ -20,9 +20,9 @@ void ToggleButtonExample::CreateExampleView(View* container) { button_ = new ToggleButton(this); - BoxLayout* layout = new BoxLayout(BoxLayout::kVertical); + auto layout = std::make_unique<BoxLayout>(BoxLayout::kVertical); layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); - container->SetLayoutManager(layout); + container->SetLayoutManager(std::move(layout)); container->AddChildView(button_); }
diff --git a/ui/views/examples/tree_view_example.cc b/ui/views/examples/tree_view_example.cc index 061cbef..c6621eb3 100644 --- a/ui/views/examples/tree_view_example.cc +++ b/ui/views/examples/tree_view_example.cc
@@ -80,7 +80,8 @@ change_title_->SetFocusForPlatform(); change_title_->set_request_focus_on_press(true); - GridLayout* layout = GridLayout::CreateAndInstall(container); + GridLayout* layout = container->SetLayoutManager( + std::make_unique<views::GridLayout>(container)); const int tree_view_column = 0; ColumnSet* column_set = layout->AddColumnSet(tree_view_column);
diff --git a/ui/views/examples/vector_example.cc b/ui/views/examples/vector_example.cc index 789082a8..7c91870 100644 --- a/ui/views/examples/vector_example.cc +++ b/ui/views/examples/vector_example.cc
@@ -48,25 +48,25 @@ AddChildView(color_input_); image_view_container_->AddChildView(image_view_); - BoxLayout* image_layout = new BoxLayout(BoxLayout::kHorizontal); + auto image_layout = std::make_unique<BoxLayout>(BoxLayout::kHorizontal); image_layout->set_cross_axis_alignment( BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); image_layout->set_main_axis_alignment( BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER); - image_view_container_->SetLayoutManager(image_layout); + image_view_container_->SetLayoutManager(std::move(image_layout)); image_view_->SetBorder(CreateSolidSidedBorder(1, 1, 1, 1, SK_ColorBLACK)); AddChildView(image_view_container_); - BoxLayout* box = new BoxLayout(BoxLayout::kVertical, gfx::Insets(10), 10); - SetLayoutManager(box); + BoxLayout* box = SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(10), 10)); box->SetFlexForView(image_view_container_, 1); file_chooser_->set_placeholder_text( base::ASCIIToUTF16("Enter a file to read")); View* file_container = new View(); BoxLayout* file_box = - new BoxLayout(BoxLayout::kHorizontal, gfx::Insets(10), 10); - file_container->SetLayoutManager(file_box); + file_container->SetLayoutManager(std::make_unique<BoxLayout>( + BoxLayout::kHorizontal, gfx::Insets(10), 10)); file_container->AddChildView(file_chooser_); file_container->AddChildView(file_go_button_); file_box->SetFlexForView(file_chooser_, 1); @@ -152,7 +152,7 @@ VectorExample::~VectorExample() {} void VectorExample::CreateExampleView(View* container) { - container->SetLayoutManager(new FillLayout()); + container->SetLayoutManager(std::make_unique<FillLayout>()); container->AddChildView(new VectorIconGallery()); }
diff --git a/ui/views/examples/webview_example.cc b/ui/views/examples/webview_example.cc index ccde6d7e..f23b646f 100644 --- a/ui/views/examples/webview_example.cc +++ b/ui/views/examples/webview_example.cc
@@ -24,7 +24,7 @@ void WebViewExample::CreateExampleView(View* container) { webview_ = new WebView(browser_context_); webview_->GetWebContents()->SetDelegate(this); - container->SetLayoutManager(new FillLayout); + container->SetLayoutManager(std::make_unique<FillLayout>()); container->AddChildView(webview_); webview_->LoadInitialURL(GURL("http://www.google.com/"));
diff --git a/ui/views/examples/widget_example.cc b/ui/views/examples/widget_example.cc index 9b7a292..59afbba 100644 --- a/ui/views/examples/widget_example.cc +++ b/ui/views/examples/widget_example.cc
@@ -45,7 +45,8 @@ DialogExample::DialogExample() { SetBackground(CreateSolidBackground(SK_ColorGRAY)); - SetLayoutManager(new BoxLayout(BoxLayout::kVertical, gfx::Insets(10), 10)); + SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(10), 10)); AddChildView(new Label(ASCIIToUTF16("Dialog contents label!"))); } @@ -74,7 +75,7 @@ void WidgetExample::CreateExampleView(View* container) { container->SetLayoutManager( - new BoxLayout(BoxLayout::kHorizontal, gfx::Insets(), 10)); + std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(), 10)); BuildButton(container, "Popup widget", POPUP); BuildButton(container, "Dialog widget", DIALOG); BuildButton(container, "Modal Dialog", MODAL_DIALOG); @@ -106,7 +107,8 @@ // If the Widget has no contents by default, add a view with a 'Close' button. if (!widget->GetContentsView()) { View* contents = new View(); - contents->SetLayoutManager(new BoxLayout(BoxLayout::kHorizontal)); + contents->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kHorizontal)); contents->SetBackground(CreateSolidBackground(SK_ColorGRAY)); BuildButton(contents, "Close", CLOSE_WIDGET); widget->SetContentsView(contents);
diff --git a/ui/views/layout/box_layout_unittest.cc b/ui/views/layout/box_layout_unittest.cc index c1e7891..8d46a6f1 100644 --- a/ui/views/layout/box_layout_unittest.cc +++ b/ui/views/layout/box_layout_unittest.cc
@@ -26,15 +26,14 @@ } // namespace TEST_F(BoxLayoutTest, Empty) { - BoxLayout* layout = - new BoxLayout(BoxLayout::kHorizontal, gfx::Insets(10), 20); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(10), 20)); EXPECT_EQ(gfx::Size(20, 20), layout->GetPreferredSize(host_.get())); } TEST_F(BoxLayoutTest, AlignmentHorizontal) { - BoxLayout* layout = new BoxLayout(BoxLayout::kHorizontal); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kHorizontal)); View* v1 = new StaticSizedView(gfx::Size(10, 20)); host_->AddChildView(v1); View* v2 = new StaticSizedView(gfx::Size(10, 10)); @@ -47,8 +46,8 @@ } TEST_F(BoxLayoutTest, AlignmentVertical) { - BoxLayout* layout = new BoxLayout(BoxLayout::kVertical); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kVertical)); View* v1 = new StaticSizedView(gfx::Size(20, 10)); host_->AddChildView(v1); View* v2 = new StaticSizedView(gfx::Size(10, 10)); @@ -61,9 +60,8 @@ } TEST_F(BoxLayoutTest, SetInsideBorderInsets) { - BoxLayout* layout = - new BoxLayout(BoxLayout::kHorizontal, gfx::Insets(20, 10)); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(20, 10))); View* v1 = new StaticSizedView(gfx::Size(10, 20)); host_->AddChildView(v1); View* v2 = new StaticSizedView(gfx::Size(10, 10)); @@ -84,8 +82,8 @@ } TEST_F(BoxLayoutTest, Spacing) { - BoxLayout* layout = new BoxLayout(BoxLayout::kHorizontal, gfx::Insets(7), 8); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(7), 8)); View* v1 = new StaticSizedView(gfx::Size(10, 20)); host_->AddChildView(v1); View* v2 = new StaticSizedView(gfx::Size(10, 20)); @@ -98,8 +96,8 @@ } TEST_F(BoxLayoutTest, Overflow) { - BoxLayout* layout = new BoxLayout(BoxLayout::kHorizontal); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kHorizontal)); View* v1 = new StaticSizedView(gfx::Size(20, 20)); host_->AddChildView(v1); View* v2 = new StaticSizedView(gfx::Size(10, 20)); @@ -130,9 +128,8 @@ } TEST_F(BoxLayoutTest, NoSpace) { - BoxLayout* layout = - new BoxLayout(BoxLayout::kHorizontal, gfx::Insets(10), 10); - host_->SetLayoutManager(layout); + host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(10), 10)); View* childView = new StaticSizedView(gfx::Size(20, 20)); host_->AddChildView(childView); host_->SetBounds(0, 0, 10, 10); @@ -141,9 +138,8 @@ } TEST_F(BoxLayoutTest, InvisibleChild) { - BoxLayout* layout = - new BoxLayout(BoxLayout::kHorizontal, gfx::Insets(10), 10); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(10), 10)); View* v1 = new StaticSizedView(gfx::Size(20, 20)); v1->SetVisible(false); host_->AddChildView(v1); @@ -156,8 +152,8 @@ } TEST_F(BoxLayoutTest, UseHeightForWidth) { - BoxLayout* layout = new BoxLayout(BoxLayout::kVertical); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kVertical)); View* v1 = new StaticSizedView(gfx::Size(20, 10)); host_->AddChildView(v1); ProportionallySizedView* v2 = new ProportionallySizedView(2); @@ -190,7 +186,8 @@ BoxLayout::Orientation orientation = i == 0 ? BoxLayout::kHorizontal : BoxLayout::kVertical; host_->RemoveAllChildViews(true); - host_->SetLayoutManager(new BoxLayout(orientation, gfx::Insets(), 5)); + host_->SetLayoutManager( + std::make_unique<BoxLayout>(orientation, gfx::Insets(), 5)); View* v1 = new StaticSizedView(gfx::Size()); host_->AddChildView(v1); View* v2 = new StaticSizedView(gfx::Size(10, 10)); @@ -211,8 +208,8 @@ // empty preferred size, simultaneously. TEST_F(BoxLayoutTest, EmptyPreferredSizeWithFlexLayoutAndChildSpacing) { host_->RemoveAllChildViews(true); - BoxLayout* layout = new BoxLayout(BoxLayout::kHorizontal, gfx::Insets(), 5); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(), 5)); View* v1 = new StaticSizedView(gfx::Size()); host_->AddChildView(v1); View* v2 = new StaticSizedView(gfx::Size(10, 10)); @@ -227,9 +224,8 @@ } TEST_F(BoxLayoutTest, MainAxisAlignmentHorizontal) { - BoxLayout* layout = - new BoxLayout(BoxLayout::kHorizontal, gfx::Insets(10), 10); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(10), 10)); View* v1 = new StaticSizedView(gfx::Size(20, 20)); host_->AddChildView(v1); @@ -264,8 +260,8 @@ } TEST_F(BoxLayoutTest, MainAxisAlignmentVertical) { - BoxLayout* layout = new BoxLayout(BoxLayout::kVertical, gfx::Insets(10), 10); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(10), 10)); View* v1 = new StaticSizedView(gfx::Size(20, 20)); host_->AddChildView(v1); @@ -300,9 +296,8 @@ } TEST_F(BoxLayoutTest, CrossAxisAlignmentHorizontal) { - BoxLayout* layout = - new BoxLayout(BoxLayout::kHorizontal, gfx::Insets(10), 10); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(10), 10)); View* v1 = new StaticSizedView(gfx::Size(20, 20)); host_->AddChildView(v1); @@ -343,8 +338,8 @@ } TEST_F(BoxLayoutTest, CrossAxisAlignmentVertical) { - BoxLayout* layout = new BoxLayout(BoxLayout::kVertical, gfx::Insets(10), 10); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(10), 10)); View* v1 = new StaticSizedView(gfx::Size(20, 20)); host_->AddChildView(v1); @@ -385,9 +380,8 @@ } TEST_F(BoxLayoutTest, FlexAll) { - BoxLayout* layout = - new BoxLayout(BoxLayout::kHorizontal, gfx::Insets(10), 10); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(10), 10)); layout->SetDefaultFlex(1); View* v1 = new StaticSizedView(gfx::Size(20, 20)); @@ -406,8 +400,8 @@ } TEST_F(BoxLayoutTest, FlexGrowVertical) { - BoxLayout* layout = new BoxLayout(BoxLayout::kVertical, gfx::Insets(10), 10); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(10), 10)); View* v1 = new StaticSizedView(gfx::Size(20, 20)); host_->AddChildView(v1); @@ -463,8 +457,8 @@ } TEST_F(BoxLayoutTest, FlexGrowHorizontalWithRemainder) { - BoxLayout* layout = new BoxLayout(BoxLayout::kHorizontal); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kHorizontal)); layout->SetDefaultFlex(1); std::vector<View*> views; for (int i = 0; i < 5; ++i) { @@ -487,8 +481,8 @@ } TEST_F(BoxLayoutTest, FlexGrowHorizontalWithRemainder2) { - BoxLayout* layout = new BoxLayout(BoxLayout::kHorizontal); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kHorizontal)); layout->SetDefaultFlex(1); std::vector<View*> views; for (int i = 0; i < 4; ++i) { @@ -510,9 +504,8 @@ } TEST_F(BoxLayoutTest, FlexShrinkHorizontal) { - BoxLayout* layout = - new BoxLayout(BoxLayout::kHorizontal, gfx::Insets(10), 10); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(10), 10)); View* v1 = new StaticSizedView(gfx::Size(20, 20)); host_->AddChildView(v1); @@ -570,8 +563,8 @@ } TEST_F(BoxLayoutTest, FlexShrinkVerticalWithRemainder) { - BoxLayout* layout = new BoxLayout(BoxLayout::kVertical); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kVertical)); View* v1 = new StaticSizedView(gfx::Size(20, 10)); host_->AddChildView(v1); View* v2 = new StaticSizedView(gfx::Size(20, 20)); @@ -620,8 +613,8 @@ } TEST_F(BoxLayoutTest, MinimumCrossAxisVertical) { - BoxLayout* layout = new BoxLayout(BoxLayout::kVertical); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kVertical)); View* v1 = new StaticSizedView(gfx::Size(20, 10)); host_->AddChildView(v1); layout->set_minimum_cross_axis_size(30); @@ -630,8 +623,8 @@ } TEST_F(BoxLayoutTest, MinimumCrossAxisHorizontal) { - BoxLayout* layout = new BoxLayout(BoxLayout::kHorizontal); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kHorizontal)); View* v1 = new StaticSizedView(gfx::Size(20, 10)); host_->AddChildView(v1); layout->set_minimum_cross_axis_size(30); @@ -640,8 +633,8 @@ } TEST_F(BoxLayoutTest, MarginsUncollapsedHorizontal) { - BoxLayout* layout = new BoxLayout(BoxLayout::kHorizontal); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kHorizontal)); View* v1 = new StaticSizedView(gfx::Size(20, 10)); v1->SetProperty(kMarginsKey, new gfx::Insets(5, 5, 5, 5)); host_->AddChildView(v1); @@ -657,9 +650,8 @@ } TEST_F(BoxLayoutTest, MarginsCollapsedHorizontal) { - BoxLayout* layout = - new BoxLayout(BoxLayout::kHorizontal, gfx::Insets(0, 0), 0, true); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>( + BoxLayout::kHorizontal, gfx::Insets(0, 0), 0, true)); View* v1 = new StaticSizedView(gfx::Size(20, 10)); v1->SetProperty(kMarginsKey, new gfx::Insets(5, 5, 5, 5)); host_->AddChildView(v1); @@ -675,8 +667,8 @@ } TEST_F(BoxLayoutTest, MarginsUncollapsedVertical) { - BoxLayout* layout = new BoxLayout(BoxLayout::kVertical); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kVertical)); View* v1 = new StaticSizedView(gfx::Size(20, 10)); v1->SetProperty(kMarginsKey, new gfx::Insets(5, 5, 5, 5)); host_->AddChildView(v1); @@ -692,9 +684,8 @@ } TEST_F(BoxLayoutTest, MarginsCollapsedVertical) { - BoxLayout* layout = - new BoxLayout(BoxLayout::kVertical, gfx::Insets(0, 0), 0, true); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>( + BoxLayout::kVertical, gfx::Insets(0, 0), 0, true)); View* v1 = new StaticSizedView(gfx::Size(20, 10)); v1->SetProperty(kMarginsKey, new gfx::Insets(5, 5, 5, 5)); host_->AddChildView(v1); @@ -710,9 +701,10 @@ } TEST_F(BoxLayoutTest, UnbalancedMarginsUncollapsedHorizontal) { - BoxLayout* layout = new BoxLayout(BoxLayout::kHorizontal); - layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); - host_->SetLayoutManager(layout); + auto layout_owner = std::make_unique<BoxLayout>(BoxLayout::kHorizontal); + layout_owner->set_cross_axis_alignment( + BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); + BoxLayout* layout = host_->SetLayoutManager(std::move(layout_owner)); View* v1 = new StaticSizedView(gfx::Size(20, 10)); v1->SetProperty(kMarginsKey, new gfx::Insets(5, 5, 4, 4)); host_->AddChildView(v1); @@ -728,10 +720,11 @@ } TEST_F(BoxLayoutTest, UnbalancedMarginsCollapsedHorizontal) { - BoxLayout* layout = - new BoxLayout(BoxLayout::kHorizontal, gfx::Insets(0, 0), 0, true); - layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); - host_->SetLayoutManager(layout); + auto layout_owner = std::make_unique<BoxLayout>(BoxLayout::kHorizontal, + gfx::Insets(0, 0), 0, true); + layout_owner->set_cross_axis_alignment( + BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); + BoxLayout* layout = host_->SetLayoutManager(std::move(layout_owner)); View* v1 = new StaticSizedView(gfx::Size(20, 10)); v1->SetProperty(kMarginsKey, new gfx::Insets(5, 5, 4, 4)); host_->AddChildView(v1); @@ -747,9 +740,10 @@ } TEST_F(BoxLayoutTest, UnbalancedMarginsUncollapsedVertical) { - BoxLayout* layout = new BoxLayout(BoxLayout::kVertical); - layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); - host_->SetLayoutManager(layout); + auto layout_owner = std::make_unique<BoxLayout>(BoxLayout::kVertical); + layout_owner->set_cross_axis_alignment( + BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); + BoxLayout* layout = host_->SetLayoutManager(std::move(layout_owner)); View* v1 = new StaticSizedView(gfx::Size(20, 10)); v1->SetProperty(kMarginsKey, new gfx::Insets(4, 5, 5, 3)); host_->AddChildView(v1); @@ -765,10 +759,11 @@ } TEST_F(BoxLayoutTest, UnbalancedMarginsCollapsedVertical) { - BoxLayout* layout = - new BoxLayout(BoxLayout::kVertical, gfx::Insets(0, 0), 0, true); - layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); - host_->SetLayoutManager(layout); + auto layout_owner = std::make_unique<BoxLayout>(BoxLayout::kVertical, + gfx::Insets(0, 0), 0, true); + layout_owner->set_cross_axis_alignment( + BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER); + BoxLayout* layout = host_->SetLayoutManager(std::move(layout_owner)); View* v1 = new StaticSizedView(gfx::Size(20, 10)); v1->SetProperty(kMarginsKey, new gfx::Insets(4, 5, 5, 3)); host_->AddChildView(v1); @@ -785,8 +780,8 @@ TEST_F(BoxLayoutTest, OverlappingCrossMarginsAlignEnd) { { - BoxLayout* layout = new BoxLayout(BoxLayout::kHorizontal); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kHorizontal)); layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_END); View* v1 = new StaticSizedView(gfx::Size(20, 4)); v1->SetProperty(kMarginsKey, new gfx::Insets(3, 0, 0, 0)); @@ -799,9 +794,8 @@ } host_->RemoveAllChildViews(true); { - BoxLayout* layout = - new BoxLayout(BoxLayout::kHorizontal, gfx::Insets(0, 0), 0, true); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>( + BoxLayout::kHorizontal, gfx::Insets(0, 0), 0, true)); layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_END); View* v1 = new StaticSizedView(gfx::Size(20, 4)); v1->SetProperty(kMarginsKey, new gfx::Insets(3, 0, 0, 0)); @@ -816,8 +810,8 @@ TEST_F(BoxLayoutTest, OverlappingCrossMarginsAlignStretch) { { - BoxLayout* layout = new BoxLayout(BoxLayout::kHorizontal); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kHorizontal)); layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_STRETCH); View* v1 = new StaticSizedView(gfx::Size(20, 4)); v1->SetProperty(kMarginsKey, new gfx::Insets(3, 0, 0, 0)); @@ -830,9 +824,8 @@ } host_->RemoveAllChildViews(true); { - BoxLayout* layout = - new BoxLayout(BoxLayout::kHorizontal, gfx::Insets(0, 0), 0, true); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>( + BoxLayout::kHorizontal, gfx::Insets(0, 0), 0, true)); layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_STRETCH); View* v1 = new StaticSizedView(gfx::Size(20, 4)); v1->SetProperty(kMarginsKey, new gfx::Insets(3, 0, 0, 0)); @@ -847,8 +840,8 @@ TEST_F(BoxLayoutTest, OverlappingCrossMarginsAlignStart) { { - BoxLayout* layout = new BoxLayout(BoxLayout::kHorizontal); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kHorizontal)); layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_START); View* v1 = new StaticSizedView(gfx::Size(20, 4)); v1->SetProperty(kMarginsKey, new gfx::Insets(0, 0, 3, 0)); @@ -861,9 +854,8 @@ } host_->RemoveAllChildViews(true); { - BoxLayout* layout = - new BoxLayout(BoxLayout::kHorizontal, gfx::Insets(0, 0), 0, true); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>( + BoxLayout::kHorizontal, gfx::Insets(0, 0), 0, true)); layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_START); View* v1 = new StaticSizedView(gfx::Size(20, 4)); v1->SetProperty(kMarginsKey, new gfx::Insets(0, 0, 3, 0)); @@ -877,8 +869,8 @@ } TEST_F(BoxLayoutTest, NegativeBetweenChildSpacing) { - BoxLayout* layout = new BoxLayout(BoxLayout::kVertical, gfx::Insets(), -10); - host_->SetLayoutManager(layout); + BoxLayout* layout = host_->SetLayoutManager( + std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(), -10)); View* v1 = new StaticSizedView(gfx::Size(20, 20)); host_->AddChildView(v1); View* v2 = new StaticSizedView(gfx::Size(20, 15));
diff --git a/ui/views/layout/fill_layout_unittest.cc b/ui/views/layout/fill_layout_unittest.cc index 93a6681..31e73e26 100644 --- a/ui/views/layout/fill_layout_unittest.cc +++ b/ui/views/layout/fill_layout_unittest.cc
@@ -18,8 +18,8 @@ static const int kDefaultHostWidth = 100; static const int kDefaultHostHeight = 200; - FillLayoutTest() : layout_(new FillLayout), host_(new View) { - host_->SetLayoutManager(layout_); + FillLayoutTest() : layout_(nullptr), host_(new View) { + layout_ = host_->SetLayoutManager(std::make_unique<FillLayout>()); SetHostSize(kDefaultHostWidth, kDefaultHostHeight); }
diff --git a/ui/views/layout/grid_layout.cc b/ui/views/layout/grid_layout.cc index 3060f64..0f3ee7aa 100644 --- a/ui/views/layout/grid_layout.cc +++ b/ui/views/layout/grid_layout.cc
@@ -775,15 +775,11 @@ // GridLayout ------------------------------------------------------------- -// static -GridLayout* GridLayout::CreateAndInstall(View* host) { - GridLayout* result = new GridLayout(host); - host->SetLayoutManager(result); - return result; +GridLayout::GridLayout(View* host) : host_(host) { + DCHECK(host); } -GridLayout::~GridLayout() { -} +GridLayout::~GridLayout() {} ColumnSet* GridLayout::AddColumnSet(int id) { DCHECK(GetColumnSet(id) == nullptr); @@ -939,17 +935,6 @@ return pref.height(); } -GridLayout::GridLayout(View* host) - : host_(host), - calculated_master_columns_(false), - remaining_row_span_(0), - current_row_(-1), - next_column_(0), - current_row_col_set_(nullptr), - adding_view_(false) { - DCHECK(host); -} - void GridLayout::SizeRowsAndColumns(bool layout, int width, int height, gfx::Size* pref) const { // Protect against clients asking for metrics during the addition of a View.
diff --git a/ui/views/layout/grid_layout.h b/ui/views/layout/grid_layout.h index b50daea..4721adf 100644 --- a/ui/views/layout/grid_layout.h +++ b/ui/views/layout/grid_layout.h
@@ -107,11 +107,7 @@ USE_PREF }; - // Creates a new GridLayout and installs it as the LayoutManager for |host|. - // The returned pointer is owned by the view and already installed as its - // layout manager. - static GridLayout* CreateAndInstall(View* host); - + explicit GridLayout(View* host); ~GridLayout() override; // See class description for what this does. @@ -192,8 +188,6 @@ void set_minimum_size(const gfx::Size& size) { minimum_size_ = size; } private: - explicit GridLayout(View* host); - // As both Layout and GetPreferredSize need to do nearly the same thing, // they both call into this method. This sizes the Columns/Rows as // appropriate. If layout is true, width/height give the width/height the @@ -234,23 +228,23 @@ View* const host_; // Whether or not we've calculated the master/linked columns. - mutable bool calculated_master_columns_; + mutable bool calculated_master_columns_ = false; // Used to verify a view isn't added with a row span that expands into // another column structure. - int remaining_row_span_; + int remaining_row_span_ = 0; // Current row. - int current_row_; + int current_row_ = -1; // Current column. - int next_column_; + int next_column_ = 0; // Column set for the current row. This is null for padding rows. - ColumnSet* current_row_col_set_; + ColumnSet* current_row_col_set_ = nullptr; // Set to true when adding a View. - bool adding_view_; + bool adding_view_ = false; // ViewStates. This is ordered by row_span in ascending order. mutable std::vector<std::unique_ptr<ViewState>> view_states_;
diff --git a/ui/views/layout/grid_layout_unittest.cc b/ui/views/layout/grid_layout_unittest.cc index f993c6f..c5c3242 100644 --- a/ui/views/layout/grid_layout_unittest.cc +++ b/ui/views/layout/grid_layout_unittest.cc
@@ -99,7 +99,10 @@ class GridLayoutTest : public testing::Test { public: - GridLayoutTest() : layout_(GridLayout::CreateAndInstall(&host_)) {} + GridLayoutTest() { + layout_ = + host_.SetLayoutManager(std::make_unique<views::GridLayout>(&host_)); + } void RemoveAll() { for (int i = host_.child_count() - 1; i >= 0; i--) @@ -118,7 +121,9 @@ class GridLayoutAlignmentTest : public testing::Test { public: - GridLayoutAlignmentTest() : layout_(GridLayout::CreateAndInstall(&host_)) { + GridLayoutAlignmentTest() { + layout_ = + host_.SetLayoutManager(std::make_unique<views::GridLayout>(&host_)); v1_.SetPreferredSize(gfx::Size(10, 20)); }
diff --git a/ui/views/touchui/touch_selection_menu_runner_views.cc b/ui/views/touchui/touch_selection_menu_runner_views.cc index 7a6c5c77..75ab64c9 100644 --- a/ui/views/touchui/touch_selection_menu_runner_views.cc +++ b/ui/views/touchui/touch_selection_menu_runner_views.cc
@@ -101,8 +101,8 @@ set_adjust_if_offscreen(true); EnableCanvasFlippingForRTLUI(true); - SetLayoutManager(new BoxLayout(BoxLayout::kHorizontal, gfx::Insets(), - kSpacingBetweenButtons)); + SetLayoutManager(std::make_unique<BoxLayout>( + BoxLayout::kHorizontal, gfx::Insets(), kSpacingBetweenButtons)); CreateButtons(); // After buttons are created, check if there is enough room between handles to
diff --git a/ui/views/widget/native_widget_aura_unittest.cc b/ui/views/widget/native_widget_aura_unittest.cc index c560b35..e767025b 100644 --- a/ui/views/widget/native_widget_aura_unittest.cc +++ b/ui/views/widget/native_widget_aura_unittest.cc
@@ -416,7 +416,7 @@ GestureTrackingView* view = new GestureTrackingView(); GestureTrackingView* child = new GestureTrackingView(); child->set_consume_gesture_event(false); - view->SetLayoutManager(new FillLayout); + view->SetLayoutManager(std::make_unique<FillLayout>()); view->AddChildView(child); std::unique_ptr<TestWidget> widget(new TestWidget()); Widget::InitParams params(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
diff --git a/ui/views/window/dialog_client_view.cc b/ui/views/window/dialog_client_view.cc index a2f8feb6..6b673090 100644 --- a/ui/views/window/dialog_client_view.cc +++ b/ui/views/window/dialog_client_view.cc
@@ -342,7 +342,8 @@ // Clobber any existing LayoutManager since it has weak references to child // Views which may be removed by SetupViews(). - GridLayout* layout = GridLayout::CreateAndInstall(button_row_container_); + GridLayout* layout = button_row_container_->SetLayoutManager( + std::make_unique<views::GridLayout>(button_row_container_)); layout->set_minimum_size(minimum_size_); SetupViews();
diff --git a/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html b/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html index ec7b7d1..4f6115b4 100644 --- a/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html +++ b/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html
@@ -18,6 +18,7 @@ cursor: pointer; display: flex; flex: 1; + font-family: inherit; font-size: 100%; /* Specifically for Mac OSX, harmless elsewhere. */ line-height: 154%; /* 20px. */ margin: 0;
diff --git a/url/ipc/OWNERS b/url/ipc/OWNERS index 2bf6612..146c3c3c 100644 --- a/url/ipc/OWNERS +++ b/url/ipc/OWNERS
@@ -1,2 +1,2 @@ -per-file *_param_traits*.*=set noparent -per-file *_param_traits*.*=file://ipc/SECURITY_OWNERS +per-file *_param_traits*.*=set noparent +per-file *_param_traits*.*=file://ipc/SECURITY_OWNERS